[kutil] Rename 'size' to 'order' when meaning 2^N
Heap allocator is a buddy allocator that deals with power-of-two block sizes. Previously it referred to both a number of bytes and an order of magnitude as a 'size'. Rename functions and variables referring to orders of magnitude to 'order'. Tags: pedantry
This commit is contained in:
@@ -7,15 +7,15 @@ namespace kutil {
|
||||
|
||||
struct heap_allocator::mem_header
|
||||
{
|
||||
mem_header(mem_header *prev, mem_header *next, uint8_t size) :
|
||||
mem_header(mem_header *prev, mem_header *next, uint8_t order) :
|
||||
m_prev(prev), m_next(next)
|
||||
{
|
||||
set_size(size);
|
||||
set_order(order);
|
||||
}
|
||||
|
||||
inline void set_size(uint8_t size) {
|
||||
inline void set_order(uint8_t order) {
|
||||
m_prev = reinterpret_cast<mem_header *>(
|
||||
reinterpret_cast<uintptr_t>(prev()) | (size & 0x3f));
|
||||
reinterpret_cast<uintptr_t>(prev()) | (order & 0x3f));
|
||||
}
|
||||
|
||||
inline void set_used(bool used) {
|
||||
@@ -30,9 +30,9 @@ struct heap_allocator::mem_header
|
||||
}
|
||||
|
||||
inline void set_prev(mem_header *prev) {
|
||||
uint8_t s = size();
|
||||
uint8_t s = order();
|
||||
m_prev = prev;
|
||||
set_size(s);
|
||||
set_order(s);
|
||||
}
|
||||
|
||||
void remove() {
|
||||
@@ -47,12 +47,12 @@ struct heap_allocator::mem_header
|
||||
|
||||
inline mem_header * buddy() const {
|
||||
return reinterpret_cast<mem_header *>(
|
||||
reinterpret_cast<uintptr_t>(this) ^ (1 << size()));
|
||||
reinterpret_cast<uintptr_t>(this) ^ (1 << order()));
|
||||
}
|
||||
|
||||
inline bool eldest() const { return this < buddy(); }
|
||||
|
||||
inline uint8_t size() const { return reinterpret_cast<uintptr_t>(m_prev) & 0x3f; }
|
||||
inline uint8_t order() const { return reinterpret_cast<uintptr_t>(m_prev) & 0x3f; }
|
||||
inline bool used() const { return reinterpret_cast<uintptr_t>(m_next) & 0x1; }
|
||||
|
||||
private:
|
||||
@@ -73,16 +73,17 @@ void *
|
||||
heap_allocator::allocate(size_t length)
|
||||
{
|
||||
size_t total = length + sizeof(mem_header);
|
||||
unsigned size = min_size;
|
||||
while (total > (1 << size)) size++;
|
||||
|
||||
kassert(size <= max_size, "Tried to allocate a block bigger than max_size");
|
||||
if (size > max_size)
|
||||
unsigned order = min_order;
|
||||
while (total > (1 << order)) order++;
|
||||
|
||||
kassert(order <= max_order, "Tried to allocate a block bigger than max_order");
|
||||
if (order > max_order)
|
||||
return nullptr;
|
||||
|
||||
mem_header *header = pop_free(size);
|
||||
mem_header *header = pop_free(order);
|
||||
header->set_used(true);
|
||||
m_allocated_size += (1 << size);
|
||||
m_allocated_size += (1 << order);
|
||||
return header + 1;
|
||||
}
|
||||
|
||||
@@ -94,66 +95,66 @@ heap_allocator::free(void *p)
|
||||
mem_header *header = reinterpret_cast<mem_header *>(p);
|
||||
header -= 1; // p points after the header
|
||||
header->set_used(false);
|
||||
m_allocated_size -= (1 << header->size());
|
||||
m_allocated_size -= (1 << header->order());
|
||||
|
||||
while (header->size() != max_size) {
|
||||
auto size = header->size();
|
||||
while (header->order() != max_order) {
|
||||
auto order = header->order();
|
||||
|
||||
mem_header *buddy = header->buddy();
|
||||
if (buddy->used() || buddy->size() != size)
|
||||
if (buddy->used() || buddy->order() != order)
|
||||
break;
|
||||
|
||||
if (get_free(size) == buddy)
|
||||
get_free(size) = buddy->next();
|
||||
if (get_free(order) == buddy)
|
||||
get_free(order) = buddy->next();
|
||||
|
||||
buddy->remove();
|
||||
|
||||
header = header->eldest() ? header : buddy;
|
||||
header->set_size(size + 1);
|
||||
header->set_order(order + 1);
|
||||
}
|
||||
|
||||
uint8_t size = header->size();
|
||||
header->set_next(get_free(size));
|
||||
get_free(size) = header;
|
||||
uint8_t order = header->order();
|
||||
header->set_next(get_free(order));
|
||||
get_free(order) = header;
|
||||
if (header->next())
|
||||
header->next()->set_prev(header);
|
||||
}
|
||||
|
||||
void
|
||||
heap_allocator::ensure_block(unsigned size)
|
||||
heap_allocator::ensure_block(unsigned order)
|
||||
{
|
||||
if (get_free(size) != nullptr)
|
||||
if (get_free(order) != nullptr)
|
||||
return;
|
||||
|
||||
if (size == max_size) {
|
||||
size_t bytes = (1 << max_size);
|
||||
if (order == max_order) {
|
||||
size_t bytes = (1 << max_order);
|
||||
if (bytes <= m_size) {
|
||||
mem_header *next = reinterpret_cast<mem_header *>(m_next);
|
||||
new (next) mem_header(nullptr, nullptr, size);
|
||||
get_free(size) = next;
|
||||
new (next) mem_header(nullptr, nullptr, order);
|
||||
get_free(order) = next;
|
||||
m_next += bytes;
|
||||
m_size -= bytes;
|
||||
}
|
||||
} else {
|
||||
mem_header *orig = pop_free(size + 1);
|
||||
mem_header *orig = pop_free(order + 1);
|
||||
if (orig) {
|
||||
mem_header *next = kutil::offset_pointer(orig, 1 << size);
|
||||
new (next) mem_header(orig, nullptr, size);
|
||||
mem_header *next = kutil::offset_pointer(orig, 1 << order);
|
||||
new (next) mem_header(orig, nullptr, order);
|
||||
|
||||
orig->set_next(next);
|
||||
orig->set_size(size);
|
||||
get_free(size) = orig;
|
||||
orig->set_order(order);
|
||||
get_free(order) = orig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heap_allocator::mem_header *
|
||||
heap_allocator::pop_free(unsigned size)
|
||||
heap_allocator::pop_free(unsigned order)
|
||||
{
|
||||
ensure_block(size);
|
||||
mem_header *block = get_free(size);
|
||||
ensure_block(order);
|
||||
mem_header *block = get_free(order);
|
||||
if (block) {
|
||||
get_free(size) = block->next();
|
||||
get_free(order) = block->next();
|
||||
block->remove();
|
||||
}
|
||||
return block;
|
||||
|
||||
Reference in New Issue
Block a user