unsigned int bitmap_find_zero_bit(const unsigned long *bitmap, unsigned int nbits, unsigned int start) { const unsigned long *p, *pend; unsigned long tmp; if (start >= nbits) return nbits; p = bitmap + BITMAP_OFFSET(start); pend = bitmap + BITMAP_OFFSET(nbits); tmp = *p | ((1 << BITMAP_SHIFT(start)) - 1); while (p < pend) { if (~tmp) goto found; tmp = *(++p); } tmp |= ~(1 << BITMAP_SHIFT(nbits)) + 1; if (!~tmp) return nbits; found: return LONG_BIT * (p - bitmap) + bit_ctz(~tmp); }
unsigned int bitmap_find_bit(const unsigned long *bitmap, unsigned int nbits, unsigned int start) { const unsigned long *p = bitmap + BITMAP_OFFSET(start); /* start word */ unsigned int shift = BITMAP_SHIFT(start); /* within the start word */ unsigned int result = start - shift; /* LONG_BIT-aligned down start */ unsigned long tmp; if (start >= nbits) return nbits; nbits -= result; tmp = *(p++) & (~0x0ul << shift); /* mask out the beginning */ while (nbits > LONG_BIT) { if (tmp) goto found; result += LONG_BIT; nbits -= LONG_BIT; tmp = *(p++); } tmp &= (~0x0ul >> (LONG_BIT - nbits)); /* ...and the ending */ if (!tmp) return result + nbits; found: return result + bit_ctz(tmp); }
static inline bool bb_table_add(bb_table_t *table, bb_entry_t *entry) { byte *bm; uint idx, offs, addr_end, idx_end, offs_end, i; if (table == BB_TABLE_IGNORE) return false; if (table->size <= entry->start + entry->size) { WARN(3, "Wrong range "PFX"-"PFX" or table size "PFX" for table "PFX"\n", (ptr_uint_t)entry->start, (ptr_uint_t)entry->start + entry->size, (ptr_uint_t)table->size, (ptr_uint_t)table); return false; } bm = table->bm; idx = BITMAP_INDEX(entry->start); /* we assume that the whole bb is seen if its start addr is seen */ if (bm[idx] == BB_TABLE_RANGE_SET) return false; offs = BITMAP_OFFSET(entry->start); if (TEST(BITMAP_MASK(offs), bm[idx])) return false; /* now we add a new bb */ PRINT(6, "Add "PFX"-"PFX" in table "PFX"\n", (ptr_uint_t)entry->start, (ptr_uint_t)entry->start + entry->size, (ptr_uint_t)table); addr_end = entry->start + entry->size - 1; idx_end = BITMAP_INDEX(addr_end); offs_end = (idx_end > idx) ? BITS_PER_BYTE-1 : BITMAP_OFFSET(addr_end); /* first byte in the bitmap */ bm[idx] |= bitmap_set[offs][offs_end]; /* set all the middle byte */ for (i = idx + 1; i < idx_end; i++) bm[i] = BB_TABLE_RANGE_SET; /* last byte in the bitmap */ if (idx_end > idx) { offs_end = BITMAP_OFFSET(addr_end); bm[idx_end] |= bitmap_set[0][offs_end]; } return true; }
static inline int bb_table_lookup(bb_table_t *table, uint addr) { byte *bm = table->bm; PRINT(5, "lookup "PFX" in bb table "PFX"\n", (ptr_uint_t)addr, (ptr_uint_t)table); /* We see this and it seems to be erroneous data from the pdb, * xref drsym_enumerate_lines() from drsyms. */ if (table->size <= addr) return BB_TABLE_ENTRY_INVALID; if (bm[BITMAP_INDEX(addr)] == 0xff || TEST(BITMAP_MASK(BITMAP_OFFSET(addr)), bm[BITMAP_INDEX(addr)])) return BB_TABLE_ENTRY_SET; return BB_TABLE_ENTRY_CLEAR; }