SmartOS/XX/Memory.cpp

188 lines
4.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Memory.h"
// 内存管理结构
typedef struct mem
{
struct mem *next; // 下一个内存块
uint len; // 数据块长度
} MemBlock;
typedef struct
{
void *free; /* Pointer to first free memory block */
void *end; /* Pointer to memory block end */
U32 blk_size; /* Memory block size */
} Block;
// 初始化内存池
bool _init_mem(void* pool, uint size)
{
if (pool == nullptr || size < sizeof(MemBlock)) return false;
/*
现有内存块位于pool大小size。
首先我们得在开头搞一个MEMP结构指示这是第一个内存块。
再者在这个内存块最后面也搞一个MEMP结构指示这是最后一个内存块它的Next是空。
所以第一个内存块的Next指向最后一个内存块。
因为还没有用所以大小是0实际持有空闲大小是Next减去当前指针。
*/
MemBlock* ptr = (MemBlock*)pool;
ptr->next = (MemBlock*)((uint)pool + size - sizeof(MemBlock));
ptr->next->next = nullptr;
ptr->len = 0;
return true;
}
// 分配内存
void* _alloc_mem(void* pool, uint size)
{
if (pool == nullptr || size == 0) return nullptr;
// 增加头部大小
size += sizeof(MemBlock);
// 确保4字节对齐
size = (size + 3) & ~3;
MemBlock* p = (MemBlock*)pool;
while (true)
{
// 当前块总大小,扣掉已经用掉的大小,得到可用大小
uint hole_size = (uint)p->next - (uint)p;
hole_size -= p->len;
// 检查大小是否足够
if (hole_size >= size) break;
p = p->next;
// 失败,位于列表尾部
if (p->next == nullptr) return nullptr;
}
if (p->len == 0)
{
// 还没有分配任何块,设置第一个元素的长度
p->len = size;
return (MemBlock*)((uint)p + sizeof(MemBlock));
}
else
{
// 插入新的元素到内存列表
MemBlock* p_new = (MemBlock*)((uint)p + p->len);
p_new->next = p->next;
p_new->len = size;
p->next = p_new;
return (MemBlock*)((uint)p_new + sizeof(MemBlock));
}
}
// 释放内存
bool _free_mem(void* pool, void *mem)
{
if (pool == nullptr || mem == nullptr) return false;
// 要释放的目标内存块
MemBlock* rs = (MemBlock*)((uint)mem - sizeof(MemBlock));
MemBlock* prv = nullptr;
MemBlock* p = (MemBlock*)pool;
while (p != rs)
{
prv = p;
p = p->next;
// 验证内存块不存在
if (p == nullptr) return false;
}
if (prv == nullptr)
// 第一块被释放仅仅设置长度为0
p->len = 0;
else
// 从链表中移除块
prv->next = p->next;
return true;
}
int _init_box(void* box_mem, uint box_size, uint blk_size)
{
/* Initialize memory block system, returns 0 if OK, 1 if fails. */
void *end;
void *blk;
void *next;
uint sizeof_bm;
// 建立内存结构注意8字节对齐还是4字节对齐
if (blk_size & BOX_ALIGN_8) {
blk_size = ((blk_size & ~BOX_ALIGN_8) + 7) & ~7;
sizeof_bm = (sizeof (struct OS_BM) + 7) & ~7;
}
else {
blk_size = (blk_size + 3) & ~3;
sizeof_bm = sizeof (struct OS_BM);
}
if (blk_size == 0) return false;
if (blk_size + sizeof_bm > box_size) return false;
// 建立内存结构
blk = ((byte *) box_mem) + sizeof_bm;
((Block*) box_mem)->free = blk;
end = ((byte *) box_mem) + box_size;
((Block*) box_mem)->end = end;
((Block*) box_mem)->blk_size = blk_size;
/* Link all free blocks using offsets. */
end = ((byte *) end) - blk_size;
while (1) {
next = ((byte *) blk) + blk_size;
if (next > end) break;
*((void **)blk) = next;
blk = next;
}
/* end marker */
*((void **)blk) = 0;
return true;
}
void* _alloc_box (void *box_mem)
{
/* Allocate a memory block and return start address. */
void **free;
do {
if ((free = (void **)__ldrex(&((Block*) box_mem)->free)) == 0) {
__clrex();
break;
}
} while (__strex((uint)*free, &((Block*) box_mem)->free));
return free;
}
void* _calloc_box(void* box_mem)
{
/* Allocate a 0-initialized memory block and return start address. */
void *free;
uint *p;
uint i;
free = _alloc_box (box_mem);
if (free)
{
p = free;
for (i = ((Block*) box_mem)->blk_size; i; i -= 4)
{
*p = 0;
p++;
}
}
return (free);
}
bool _free_box(void* box_mem, void* box)
{
if (box < box_mem || box >= ((Block*) box_mem)->end) return false;
do {
*((void **)box) = (void *)__ldrex(&((Block*) box_mem)->free);
} while (__strex ((uint)box, &((Block*) box_mem)->free));
return true;
}