use multi-word bitmap to support up to 256 slots
This commit is contained in:
parent
5e2f03296e
commit
cc9699f1b4
73
malloc.c
73
malloc.c
@ -40,7 +40,7 @@ static union {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct slab_metadata {
|
struct slab_metadata {
|
||||||
u64 bitmap;
|
u64 bitmap[4];
|
||||||
struct slab_metadata *next;
|
struct slab_metadata *next;
|
||||||
struct slab_metadata *prev;
|
struct slab_metadata *prev;
|
||||||
u64 canary_value;
|
u64 canary_value;
|
||||||
@ -190,15 +190,15 @@ static struct slab_metadata *alloc_metadata(struct size_class *c, size_t slab_si
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void set_slot(struct slab_metadata *metadata, size_t index) {
|
static void set_slot(struct slab_metadata *metadata, size_t index) {
|
||||||
metadata->bitmap |= 1UL << index;
|
metadata->bitmap[index / 64] |= 1UL << index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_slot(struct slab_metadata *metadata, size_t index) {
|
static void clear_slot(struct slab_metadata *metadata, size_t index) {
|
||||||
metadata->bitmap &= ~(1UL << index);
|
metadata->bitmap[index / 64] &= ~(1UL << index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_slot(struct slab_metadata *metadata, size_t index) {
|
static bool get_slot(struct slab_metadata *metadata, size_t index) {
|
||||||
return (metadata->bitmap >> index) & 1UL;
|
return (metadata->bitmap[index / 64] >> index) & 1UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 get_mask(size_t slots) {
|
static u64 get_mask(size_t slots) {
|
||||||
@ -206,39 +206,64 @@ static u64 get_mask(size_t slots) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t get_free_slot(struct random_state *rng, size_t slots, struct slab_metadata *metadata) {
|
static size_t get_free_slot(struct random_state *rng, size_t slots, struct slab_metadata *metadata) {
|
||||||
if (slots > 64) {
|
|
||||||
slots = 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 masked = metadata->bitmap | get_mask(slots);
|
|
||||||
if (masked == ~0UL) {
|
|
||||||
fatal_error("no zero bits");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SLOT_RANDOMIZE) {
|
if (SLOT_RANDOMIZE) {
|
||||||
// randomize start location for linear search (uniform random choice is too slow)
|
// randomize start location for linear search (uniform random choice is too slow)
|
||||||
u64 random_split = ~(~0UL << get_random_u16_uniform(rng, slots));
|
unsigned random_index = get_random_u16_uniform(rng, slots);
|
||||||
|
unsigned first_bitmap = random_index / 64;
|
||||||
|
u64 random_split = ~(~0UL << (random_index - first_bitmap * 64));
|
||||||
|
|
||||||
size_t slot = ffzl(masked | random_split);
|
for (unsigned i = first_bitmap; i <= slots / 64; i++) {
|
||||||
if (slot) {
|
u64 masked = metadata->bitmap[i];
|
||||||
return slot - 1;
|
if (i == slots / 64) {
|
||||||
|
masked |= get_mask(slots - i * 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == first_bitmap) {
|
||||||
|
masked |= random_split;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (masked == ~0UL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ffzl(masked) - 1 + i * 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ffzl(masked) - 1;
|
for (unsigned i = 0; i <= slots / 64; i++) {
|
||||||
|
u64 masked = metadata->bitmap[i];
|
||||||
|
if (i == slots / 64) {
|
||||||
|
masked |= get_mask(slots - i * 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (masked == ~0UL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ffzl(masked) - 1 + i * 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal_error("no zero bits");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool has_free_slots(size_t slots, struct slab_metadata *metadata) {
|
static bool has_free_slots(size_t slots, struct slab_metadata *metadata) {
|
||||||
if (slots > 64) {
|
if (slots <= 64) {
|
||||||
slots = 64;
|
u64 masked = metadata->bitmap[0] | get_mask(slots);
|
||||||
}
|
|
||||||
|
|
||||||
u64 masked = metadata->bitmap | get_mask(slots);
|
|
||||||
return masked != ~0UL;
|
return masked != ~0UL;
|
||||||
|
} else if (slots <= 128) {
|
||||||
|
u64 masked = metadata->bitmap[1] | get_mask(slots - 64);
|
||||||
|
return metadata->bitmap[0] != ~0UL || masked != ~0UL;
|
||||||
|
} else if (slots <= 192) {
|
||||||
|
u64 masked = metadata->bitmap[2] | get_mask(slots - 128);
|
||||||
|
return metadata->bitmap[0] != ~0UL || metadata->bitmap[1] != ~0UL || masked != ~0UL;
|
||||||
|
}
|
||||||
|
u64 masked = metadata->bitmap[3] | get_mask(slots - 192);
|
||||||
|
return metadata->bitmap[0] != ~0UL || metadata->bitmap[1] != ~0UL || metadata->bitmap[2] != ~0UL || masked != ~0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_free_slab(struct slab_metadata *metadata) {
|
static bool is_free_slab(struct slab_metadata *metadata) {
|
||||||
return !metadata->bitmap;
|
return !metadata->bitmap[0] && !metadata->bitmap[1] && !metadata->bitmap[2] &&
|
||||||
|
!metadata->bitmap[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct slab_metadata *get_metadata(struct size_class *c, void *p) {
|
static struct slab_metadata *get_metadata(struct size_class *c, void *p) {
|
||||||
|
Loading…
Reference in New Issue
Block a user