/**************************************************************** * * * Copyright 2001, 2007 Fidelity Information Services, Inc * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * * under a license. If you do not know the terms of * * the license, please stop and do not read further. * * * ****************************************************************/ #include "mdef.h" #include "gdsroot.h" #include "gdsblk.h" #include "gdsbml.h" #define MAX_FFS_SIZE 32 /* Returns the location of the first set bit in the field. */ /* The search starts at the hint and does not wrap */ int4 bm_find_blk(int4 hint, sm_uc_ptr_t base_addr, int4 total_bits, boolean_t *used) { int4 bits; sm_uc_ptr_t ptr, top; unsigned char valid; assert(hint < total_bits); total_bits *= BML_BITS_PER_BLK; /* Currently bm_find_blk has been coded to assume that if "hint" is * non-zero then it is less than total_bits. We better assert that. */ if (hint) { ptr = base_addr + (hint * BML_BITS_PER_BLK) / 8; top = base_addr + (total_bits + 7) / 8 - 1; if (ptr == top) { bits = total_bits % 8; if (bits == 6) valid = *ptr & 63; else if (bits == 4) valid = *ptr & 15; else if (bits == 2) valid = *ptr & 3; else valid = *ptr; } else valid = *ptr; switch (hint % (8 / BML_BITS_PER_BLK)) { case 0: break; case 1: valid = valid & 252; break; case 2: valid = valid & 240; break; case 3: valid = valid & 192; break; } if (valid) { if (valid & 1) { if (valid & 2) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK)); } else if (valid & 4) { if (valid & 8) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 1); } else if (valid & 16) { if (valid & 32) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 2); } else { if (valid & 128) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 3); } } ptr++; } else ptr = base_addr; for (top = base_addr + (total_bits +7) / 8 - 1; ptr < top; ptr++) { if (*ptr) { if (*ptr & 1) { if (*ptr & 2) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK)); } else if (*ptr & 4) { if (*ptr & 8) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 1); } else if (*ptr & 16) { if (*ptr & 32) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 2); } else { if (*ptr & 128) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 3); } } } if ((ptr == top) && *ptr) /* Special processing for last byte--may be only partially valid , if had hint may */ { bits = total_bits % 8; /* have already done last byte, then ptr will be greater than top */ if (bits == 6) valid = *ptr & 63; else if (bits == 4) valid = *ptr & 15; else if (bits == 2) valid = *ptr & 3; else valid = *ptr; if (valid) { if (valid & 1) { if (valid & 2) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK)); } else if (valid & 4) { if (valid & 8) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 1); } else if (valid & 16) { if (valid & 32) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 2); } else { if (valid & 128) *used = TRUE; else *used = FALSE; return (int4)((ptr - base_addr) * (8 / BML_BITS_PER_BLK) + 3); } } } return -1; }