/** * Test bit in bitmap * * @v bitmap Bitmap * @v bit Bit index * @ret is_set Bit is set */ int bitmap_test ( struct bitmap *bitmap, unsigned int bit ) { unsigned int index = BITMAP_INDEX ( bit ); bitmap_block_t mask = BITMAP_MASK ( bit ); if ( bit >= bitmap->length ) return 0; return ( bitmap->blocks[index] & mask ); }
/* * Sets a given bit in the bitmap. If the bit is already set * it returns -1, 0 otherwise. */ int bitmap_set(bitmap_t bitmap, uint32_t bit) { if(bitmap_is_set(bitmap, bit)) return -1; bitmap[bit/BITMAP_BITS_PER_ENTRY] |= BITMAP_MASK(BITMAP_REMAINING_BITS(bit)); return 0; }
/** * Set bit in bitmap * * @v bitmap Bitmap * @v bit Bit index */ void bitmap_set ( struct bitmap *bitmap, unsigned int bit ) { unsigned int index = BITMAP_INDEX ( bit ); bitmap_block_t mask = BITMAP_MASK ( bit ); DBGC ( bitmap, "Bitmap %p setting bit %d\n", bitmap, bit ); /* Update bitmap */ bitmap->blocks[index] |= mask; /* Update first gap counter */ while ( bitmap_test ( bitmap, bitmap->first_gap ) ) { bitmap->first_gap++; } }
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; }
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; }
void free_pages(struct buddy *pool, struct page *page) { struct page *buddy; struct buddy_freelist *freelist; unsigned int order, index; order = GET_PAGE_ORDER(page); freelist = &pool->free[order]; index = PAGE_INDEX(page->addr); pool->nr_free += 1U << order; while (order < BUDDY_MAX_ORDER) { BITMAP_TOGGLE(freelist->bitmap, index, order); /* If it was 0 before toggling, it means both of buddies * were allocated. So nothing can be merged to upper order * as one of them is still allocated. Otherwise, both of * them are free now. Therefore merge it to upper order. */ if (BITMAP_MASK(freelist->bitmap, index, order)) break; /* find buddy and detach it from current order to merge */ buddy = &mem_map[index ^ (1U << order)]; list_del(&buddy->link); /* grab the first address of merging buddies */ index &= ~(1U << order); order++; freelist++; } list_add(&mem_map[index].link, &freelist->list); RESET_PAGE_FLAG(page, PAGE_BUDDY); }
/* * Returns if the bit is set or not */ int bitmap_is_set(bitmap_t bitmap, uint32_t bit) { return bitmap[bit / BITMAP_BITS_PER_ENTRY] & BITMAP_MASK(BITMAP_REMAINING_BITS(bit)); }