37 static inline int left_child(
int i)
39 return ((i << 1) + 1);
42 static inline int right_child(
int i)
44 return ((i << 1) + 2);
47 static inline int parent(
int i)
49 return (((i + 1) >> 1) - 1);
52 static inline bool is_power_of_2(
size_t i)
54 return !(i & (i - 1));
57 static inline size_t next_power_of_2(
size_t size)
77 if (!requested_size) {
81 size_t fragments = (requested_size >> BUDDY_BLOCK_SIZE_EXP) + (B_CTZ(requested_size) < BUDDY_BLOCK_SIZE_EXP);
82 size_t nodes = 2 * fragments - 1;
83 struct buddy *
self = rsalloc(
sizeof(
struct buddy) + nodes *
sizeof(
size_t));
86 self->size = fragments;
88 size_t i, node_size = fragments << 1;
89 for (i = 0; i < nodes; i++) {
90 if (is_power_of_2(i + 1)) {
93 self->longest[i] = node_size;
98 void buddy_destroy(
struct buddy *
self)
108 requested_blocks = next_power_of_2(requested_blocks);
111 if (self->longest[0] < requested_blocks) {
119 for (node_size = self->size; node_size > requested_blocks; node_size >>= 1) {
121 if (self->longest[left_child(i)] >= requested_blocks) {
129 self->longest[i] = 0;
131 size_t offset = (i + 1) * node_size - self->size;
135 self->longest[i] =
max(self->longest[left_child(i)], self->longest[right_child(i)]);
141 static void buddy_free(
struct buddy *
self,
size_t offset)
144 size_t node_size = 1;
145 int i = offset +
self->size - 1;
149 for (; i &&
self->longest[i]; i = parent(i)) {
153 self->longest[i] = node_size;
159 size_t left_longest =
self->longest[left_child(i)];
160 size_t right_longest =
self->longest[right_child(i)];
162 if (left_longest + right_longest == node_size) {
163 self->longest[i] = node_size;
165 self->longest[i] =
max(left_longest, right_longest);
171 void* allocate_buddy_memory(
struct buddy*
self,
void* base_mem,
size_t requested_size)
173 if (
unlikely(!requested_size ||
self == NULL))
176 size_t requested_blocks = (requested_size >> BUDDY_BLOCK_SIZE_EXP) + (B_CTZ(requested_size) < BUDDY_BLOCK_SIZE_EXP);
177 if (
unlikely(requested_blocks > self->size))
180 size_t offset =
buddy_alloc(
self, requested_blocks);
184 return (
char *)base_mem + (offset << BUDDY_BLOCK_SIZE_EXP);
187 void free_buddy_memory(
struct buddy *
self,
void *base_mem,
void *ptr)
192 size_t offset = ((
char *)ptr - (
char *)base_mem) >> BUDDY_BLOCK_SIZE_EXP;
196 buddy_free(
self, offset);
#define spinlock_init(s)
Spinlock initialization.
static size_t buddy_alloc(struct buddy *self, size_t requested_blocks)
Dynamic Memory Logger and Restorer (DyMeLoR)
Memory Manager main header.
void spin_lock(spinlock_t *s)
#define max(a, b)
Macro to find the maximum among two values.
#define unlikely(exp)
Optimize the branch as likely not taken.
struct buddy * buddy_new(size_t requested_size)
void spin_unlock(spinlock_t *s)