|
2 | 2 | #include <stddef.h> |
3 | 3 | #include <kernel.h> |
4 | 4 |
|
5 | | -#define BUDDY_MAX_ORDER 29 |
6 | | -#define BUDDY_MIN_ORDER 6 |
7 | | - |
8 | 5 | static inline size_t order_size(int order) { |
9 | 6 | return (size_t)1 << order; |
10 | 7 | } |
@@ -87,14 +84,15 @@ static buddy_region_t *buddy_grow(buddy_allocator_t *alloc) { |
87 | 84 | } |
88 | 85 |
|
89 | 86 | size_t size = 1UL << grow; |
90 | | - void *pool = kmalloc(size); |
| 87 | + void *pool = kmalloc_aligned(size, 8); |
91 | 88 | if (!pool) { |
92 | 89 | return NULL; |
93 | 90 | } |
94 | 91 |
|
95 | | - buddy_region_t *region = (buddy_region_t *)kmalloc(sizeof(buddy_region_t)); |
| 92 | + buddy_region_t *region = (buddy_region_t *)kmalloc_aligned(sizeof(buddy_region_t), 8); |
96 | 93 | if (!region) { |
97 | | - kfree_null(&pool); |
| 94 | + kfree_aligned(pool); |
| 95 | + pool = NULL; |
98 | 96 | return NULL; |
99 | 97 | } |
100 | 98 |
|
@@ -200,6 +198,62 @@ void *buddy_malloc(buddy_allocator_t *alloc, size_t size) { |
200 | 198 | return NULL; // completely out of memory |
201 | 199 | } |
202 | 200 |
|
| 201 | +void* buddy_malloc_aligned(buddy_allocator_t* alloc, size_t size, size_t align) |
| 202 | +{ |
| 203 | + if (!alloc || size == 0) { |
| 204 | + return NULL; |
| 205 | + } |
| 206 | + |
| 207 | + if (align <= 8) { |
| 208 | + return buddy_malloc(alloc, size); |
| 209 | + } |
| 210 | + |
| 211 | + if ((align & (align - 1)) != 0) { |
| 212 | + dprintf("buddy_malloc_aligned: alignment must be power of two (got %lu)\n", align); |
| 213 | + return NULL; |
| 214 | + } |
| 215 | + |
| 216 | + /* allocate extra space for alignment slack + pointer storage */ |
| 217 | + size_t total = size + align - 1 + sizeof(void*); |
| 218 | + uint8_t* raw = (uint8_t*)buddy_malloc(alloc, total); |
| 219 | + if (!raw) { |
| 220 | + return NULL; |
| 221 | + } |
| 222 | + |
| 223 | + uintptr_t aligned = ((uintptr_t)(raw + sizeof(void*) + (align - 1))) & ~(uintptr_t)(align - 1); |
| 224 | + |
| 225 | + /* store original pointer just before aligned block */ |
| 226 | + void** save = (void**)aligned; |
| 227 | + save[-1] = raw; |
| 228 | + |
| 229 | + return (void*)aligned; |
| 230 | +} |
| 231 | + |
| 232 | +void buddy_free_aligned(buddy_allocator_t* alloc, void* ptr, size_t align) |
| 233 | +{ |
| 234 | + if (!alloc || !ptr) { |
| 235 | + return; |
| 236 | + } |
| 237 | + |
| 238 | + if (align <= 8) { |
| 239 | + buddy_free(alloc, ptr); |
| 240 | + return; |
| 241 | + } |
| 242 | + |
| 243 | + if ((align & (align - 1)) != 0) { |
| 244 | + dprintf("buddy_free_aligned: alignment must be power of two (got %lu)\n", align); |
| 245 | + return; |
| 246 | + } |
| 247 | + |
| 248 | + void** save = (void**)ptr; |
| 249 | + if (!save[-1]) { |
| 250 | + dprintf("buddy_free_aligned: missing backing pointer\n"); |
| 251 | + return; |
| 252 | + } |
| 253 | + |
| 254 | + buddy_free(alloc, save[-1]); |
| 255 | +} |
| 256 | + |
203 | 257 | void buddy_free(buddy_allocator_t *alloc, const void *ptr) { |
204 | 258 | if (!ptr || !alloc) { |
205 | 259 | return; |
@@ -270,8 +324,10 @@ void buddy_destroy(buddy_allocator_t *alloc) { |
270 | 324 | while (r) { |
271 | 325 | buddy_region_t *next = r->next; |
272 | 326 |
|
273 | | - kfree_null(&r->pool); // free the pool and null it |
274 | | - kfree_null(&r); // free the region struct itself and null that pointer |
| 327 | + kfree_aligned(r->pool); // free the pool and null it |
| 328 | + kfree_aligned(r); // free the region struct itself and null that pointer |
| 329 | + r->pool = NULL; |
| 330 | + r = NULL; |
275 | 331 |
|
276 | 332 | r = next; // use the saved "next" to continue traversal |
277 | 333 | } |
|
0 commit comments