97 lines
3.1 KiB
C
97 lines
3.1 KiB
C
#ifndef INCLUDED_C_BUDDYALLOCATOR_H
|
|
#define INCLUDED_C_BUDDYALLOCATOR_H
|
|
|
|
#ifndef INCLUDED_C_BUDDY_H
|
|
#include <c_Buddy.h>
|
|
#endif /*INCLUDED_C_BUDDY_H*/
|
|
|
|
|
|
#ifndef INCLUDED_C_ALLOCATOR_H
|
|
#include <c_Allocator.h>
|
|
#endif /*INCLUDED_C_ALLOCATOR_H*/
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
typedef struct {
|
|
c_Buddy_t* buddy;
|
|
}c_BuddyAllocator_t;
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_BuddyAllocator_Init(c_BuddyAllocator_t* allocator, c_Buddy_t* buddy) {
|
|
allocator->buddy = buddy;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
C_ALLOCATOR_ALLOC_FN(c_BuddyAllocator_Alloc) {
|
|
c_BuddyAllocator_t* self = (c_BuddyAllocator_t*)ud;
|
|
if (!self || !self->buddy) return NULL;
|
|
return c_Buddy_Alloc(self->buddy, (int)nBytes);
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
C_ALLOCATOR_FREE_FN(c_BuddyAllocator_Free) {
|
|
c_BuddyAllocator_t* self = (c_BuddyAllocator_t*)ud;
|
|
if (!self || !self->buddy) return;
|
|
c_Buddy_Free(self->buddy, ptr);
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
C_ALLOCATOR_REALLOC_FN(c_BuddyAllocator_Realloc) {
|
|
c_BuddyAllocator_t* self = (c_BuddyAllocator_t*)ud;
|
|
if (!self || !self->buddy) return NULL;
|
|
// 情况 1: 指针为空,直接分配新内存
|
|
if (!ptr) {
|
|
return c_Buddy_Alloc(self->buddy, (int)nNewSize);
|
|
}
|
|
// 情况 2: 新大小为 0,直接释放内存
|
|
if (nNewSize==0) {
|
|
c_Buddy_Free(self->buddy, ptr);
|
|
return NULL;
|
|
}
|
|
// 核心优化:利用 Header 逆向获取该块在底层伙伴系统中的真实物理大小
|
|
const c_BuddyBlock_t *block = (c_BuddyBlock_t *) ((uint8_t *) ptr - self->buddy->alignment);
|
|
const int actual_block_size = block->size;
|
|
|
|
// 【就地复用判定】:如果新申请的大小没有超过当前伙伴块的物理承载上限,并且新大小不至于小到需要缩容割裂
|
|
// 直接返回原指针,零拷贝,零内存搬迁!
|
|
if ((int)nNewSize <= actual_block_size && (int)nNewSize > (actual_block_size / 2)) {
|
|
return ptr;
|
|
}
|
|
|
|
// 情况 3: 伙伴块大小不匹配(需要升级或降级阶数),申请新块
|
|
void* new_ptr = c_Buddy_Alloc(self->buddy, (int)nNewSize);
|
|
if (!new_ptr) return NULL;
|
|
|
|
// 计算安全的拷贝长度
|
|
const c_size_t copy_size = ((c_size_t)actual_block_size < nNewSize) ? (c_size_t)actual_block_size : nNewSize;
|
|
|
|
// 数据迁移
|
|
memcpy(new_ptr, ptr, copy_size);
|
|
|
|
// 释放旧伙伴块
|
|
c_Buddy_Free(self->buddy, ptr);
|
|
|
|
return new_ptr;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_Allocator_t c_BuddyAllocator_Build(c_BuddyAllocator_t* self, c_Buddy_t* buddy) {
|
|
c_BuddyAllocator_Init(self, buddy);
|
|
c_Allocator_t allocator={0};
|
|
allocator.ud = self;
|
|
allocator.alloc = c_BuddyAllocator_Alloc;
|
|
allocator.free = c_BuddyAllocator_Free;
|
|
allocator.realloc = c_BuddyAllocator_Realloc;
|
|
return allocator;
|
|
}
|
|
|
|
#endif /*INCLUDED_C_BUDDYALLOCATOR_H*/
|