1. 增加内存分配器
This commit is contained in:
parent
9cebbd2bc7
commit
da4f8f8d23
101
include/HMem.h
Normal file
101
include/HMem.h
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 日期: 2026-03-31
|
||||
* 作者: coffee
|
||||
* 描述: 基于 HTlsf 的引用计数内存管理模块
|
||||
* 单例模式,只需初始化一次
|
||||
* 支持引用计数、自动释放、外部内存拷贝转换
|
||||
*/
|
||||
|
||||
#ifndef _H_MEM_H_
|
||||
#define _H_MEM_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化内存管理器(单例模式,只需调用一次)
|
||||
* @param buffer 外部缓冲区
|
||||
* @param size 缓冲区大小
|
||||
* @return 成功返回1, 失败返回0
|
||||
*/
|
||||
uint8_t HMemInit(void *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief 判断是否已初始化
|
||||
*/
|
||||
uint8_t HMemIsReady(void);
|
||||
|
||||
/**
|
||||
* @brief 分配内存
|
||||
* @param size 请求大小
|
||||
* @return 成功返回内存指针, 失败返回NULL
|
||||
*/
|
||||
void *HMemMalloc(size_t size);
|
||||
|
||||
/**
|
||||
* @brief 分配并清零内存
|
||||
* @param num 元素数量
|
||||
* @param size 每个元素大小
|
||||
* @return 成功返回内存指针, 失败返回NULL
|
||||
*/
|
||||
void *HMemCalloc(size_t num, size_t size);
|
||||
|
||||
/**
|
||||
* @brief 重新分配内存
|
||||
* @param ptr 原内存指针
|
||||
* @param size 新大小
|
||||
* @return 成功返回内存指针, 失败返回NULL (原内存保持不变)
|
||||
*/
|
||||
void *HMemRealloc(void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief 释放内存 (引用计数为0时才真正释放)
|
||||
* @param ptr 内存指针
|
||||
* @return 成功返回1, 失败返回0
|
||||
*/
|
||||
uint8_t HMemFree(void *ptr);
|
||||
|
||||
/**
|
||||
* @brief 增加引用计数或拷贝外部内存
|
||||
* @param ptr 内存指针 (可以是外部内存)
|
||||
* @param size 如果是外部内存,指定要拷贝的大小;如果是 HMem 内存,此参数被忽略
|
||||
* @return
|
||||
* - 如果是 HMem 分配的内存, 返回 ptr (引用计数+1)
|
||||
* - 如果是外部内存, 返回新分配的内存指针 (内容已拷贝)
|
||||
* - 内存不足返回 NULL
|
||||
*/
|
||||
void *HMemAddRef(void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief 获取当前引用计数
|
||||
* @param ptr 内存指针
|
||||
* @return 引用计数, 如果不是 HMem 分配的返回 0
|
||||
*/
|
||||
uint32_t HMemGetRefCount(void *ptr);
|
||||
|
||||
/**
|
||||
* @brief 判断指针是否由 HMem 分配
|
||||
* @param ptr 内存指针
|
||||
* @return 是返回1, 否返回0
|
||||
*/
|
||||
uint8_t HMemIsManaged(void *ptr);
|
||||
|
||||
/**
|
||||
* @brief 获取可用内存大小
|
||||
*/
|
||||
size_t HMemGetFreeSize(void);
|
||||
|
||||
/**
|
||||
* @brief 获取已使用内存大小
|
||||
*/
|
||||
size_t HMemGetUsedSize(void);
|
||||
|
||||
/**
|
||||
* @brief 获取总容量
|
||||
*/
|
||||
size_t HMemGetCapacity(void);
|
||||
|
||||
|
||||
#endif // _H_MEM_H_
|
||||
@ -54,6 +54,14 @@ size_t HTlsfPoolOverhead(void);
|
||||
*/
|
||||
size_t HTlsfMinBufferSize(void);
|
||||
|
||||
/**
|
||||
* @brief 初始化所需的最大原始内存大小
|
||||
*
|
||||
* 说明:
|
||||
* 返回值已包含最坏情况下的对齐填充
|
||||
*/
|
||||
size_t HTlsfMaxBufferSize(void);
|
||||
|
||||
/**
|
||||
* @brief 初始化 TLSF 内存池
|
||||
* @param htlsf 上下文
|
||||
|
||||
303
src/HMem.c
Normal file
303
src/HMem.c
Normal file
@ -0,0 +1,303 @@
|
||||
/**
|
||||
* 日期: 2026-03-31
|
||||
* 作者: coffee
|
||||
* 描述: 基于 HTlsf 的引用计数内存管理模块实现
|
||||
* 优化版:头部仅4字节,使用位域结构
|
||||
*/
|
||||
|
||||
#include "HMem.h"
|
||||
#include "HTlsf.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef LogD
|
||||
#define LogD(...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 头部布局 (4字节):
|
||||
* - userSize: 16 bits, 用户请求大小 (最大 65535 字节)
|
||||
* - magic: 10 bits, 魔数 (0x2AA = 0b1010101010)
|
||||
* - refCount: 6 bits, 引用计数 (最大 63)
|
||||
*/
|
||||
|
||||
#define HMEM_MAGIC_VALUE 0x2AAu
|
||||
#define HMEM_REFCOUNT_MAX 63u
|
||||
#define HMEM_SIZE_MAX 65535u
|
||||
|
||||
typedef struct __attribute__((packed)) HMemHeader {
|
||||
uint16_t userSize; /* 用户请求大小 */
|
||||
uint16_t refCount :6; /* 引用计数 */
|
||||
uint16_t magic :10; /* 魔数 */
|
||||
} HMemHeader;
|
||||
|
||||
#define HMEM_HEADER_SIZE sizeof(HMemHeader)
|
||||
|
||||
/* 编译期确保头部大小为4字节 */
|
||||
typedef char HMemHeaderSizeCheck[HMEM_HEADER_SIZE == 4 ? 1 : -1];
|
||||
|
||||
/* 对齐辅助 */
|
||||
#define HMEM_ALIGN_SIZE sizeof(void*)
|
||||
#define HMEM_ALIGN_UP(x) (((x) + HMEM_ALIGN_SIZE - 1) & ~(HMEM_ALIGN_SIZE - 1))
|
||||
#define HMEM_USER_OFFSET HMEM_ALIGN_UP(HMEM_HEADER_SIZE)
|
||||
|
||||
/* 全局单例 */
|
||||
static HTlsf sTlsf;
|
||||
|
||||
static uint8_t PtrMayBeInPool(const void *ptr) {
|
||||
if (!HTlsfIsReady(&sTlsf) || ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t poolStart = (uintptr_t)sTlsf.mem;
|
||||
uintptr_t poolEnd = poolStart + sTlsf.memSize;
|
||||
uintptr_t userPtr = (uintptr_t)ptr;
|
||||
|
||||
return userPtr >= (poolStart + HMEM_USER_OFFSET) && userPtr < poolEnd;
|
||||
}
|
||||
|
||||
static HMemHeader *GetHeader(const void *ptr) {
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PtrMayBeInPool(ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (HMemHeader *)((uint8_t *)ptr - HMEM_USER_OFFSET);
|
||||
}
|
||||
|
||||
static void *GetUserPtr(HMemHeader *header) {
|
||||
if (header == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (void *)((uint8_t *)header + HMEM_USER_OFFSET);
|
||||
}
|
||||
|
||||
static uint8_t IsValidHeader(const HMemHeader *header) {
|
||||
if (header == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return header->magic == HMEM_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
static uint8_t IsReady(void) {
|
||||
return HTlsfIsReady(&sTlsf);
|
||||
}
|
||||
|
||||
uint8_t HMemInit(void *buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size > HTlsfMaxBufferSize()) {
|
||||
size = HTlsfMaxBufferSize();
|
||||
}
|
||||
|
||||
if (HTlsfInit(&sTlsf, buffer, size)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t HMemIsReady(void) {
|
||||
return IsReady();
|
||||
}
|
||||
|
||||
void *HMemMalloc(size_t size) {
|
||||
if (!IsReady() || size == 0 || size > HMEM_SIZE_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 分配时加上头部空间 */
|
||||
size_t totalSize = HMEM_USER_OFFSET + size;
|
||||
void *raw = HTlsfMalloc(&sTlsf, totalSize);
|
||||
if (raw == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 初始化头部 */
|
||||
HMemHeader *header = (HMemHeader *)raw;
|
||||
header->magic = HMEM_MAGIC_VALUE;
|
||||
header->refCount = 1;
|
||||
header->userSize = (uint16_t)size;
|
||||
|
||||
return GetUserPtr(header);
|
||||
}
|
||||
|
||||
void *HMemCalloc(size_t num, size_t size) {
|
||||
if (!IsReady() || num == 0 || size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (num > (SIZE_MAX / size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t total = num * size;
|
||||
void *ptr = HMemMalloc(total);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, total);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *HMemRealloc(void *ptr, size_t size) {
|
||||
if (!IsReady()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size > HMEM_SIZE_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ptr == NULL 等价于 malloc */
|
||||
if (ptr == NULL) {
|
||||
return HMemMalloc(size);
|
||||
}
|
||||
|
||||
/* size == 0 等价于 free */
|
||||
if (size == 0) {
|
||||
HMemFree(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
if (!IsValidHeader(header)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t oldSize = header->userSize;
|
||||
|
||||
/* 如果新大小相同,直接返回 */
|
||||
if (size == oldSize) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (header->refCount == 1u) {
|
||||
size_t totalSize = HMEM_USER_OFFSET + size;
|
||||
void *raw = HTlsfRealloc(&sTlsf, header, totalSize);
|
||||
if (raw == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
header = (HMemHeader *)raw;
|
||||
header->magic = HMEM_MAGIC_VALUE;
|
||||
header->refCount = 1u;
|
||||
header->userSize = (uint16_t)size;
|
||||
return GetUserPtr(header);
|
||||
}
|
||||
|
||||
/* 分配新内存 */
|
||||
void *newPtr = HMemMalloc(size);
|
||||
if (newPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 拷贝数据 */
|
||||
size_t copySize = (oldSize < size) ? oldSize : size;
|
||||
memcpy(newPtr, ptr, copySize);
|
||||
|
||||
/* 释放旧内存 */
|
||||
HMemFree(ptr);
|
||||
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
uint8_t HMemFree(void *ptr) {
|
||||
if (!IsReady() || ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
if (!IsValidHeader(header)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 引用计数减一 */
|
||||
if (header->refCount > 0) {
|
||||
--header->refCount;
|
||||
}
|
||||
|
||||
/* 引用计数为0时才真正释放 */
|
||||
if (header->refCount == 0) {
|
||||
header->magic = 0; /* 清除魔数,防止再次释放 */
|
||||
HTlsfFree(&sTlsf, header);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *HMemAddRef(void *ptr, size_t size) {
|
||||
if (!IsReady() || ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
|
||||
/* 如果是 HMem 分配的内存 */
|
||||
if (IsValidHeader(header)) {
|
||||
if (header->refCount < HMEM_REFCOUNT_MAX) {
|
||||
++header->refCount;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* 不是 HMem 分配的内存,需要拷贝到新内存 */
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *newPtr = HMemMalloc(size);
|
||||
if (newPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(newPtr, ptr, size);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
uint32_t HMemGetRefCount(void *ptr) {
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
if (!IsValidHeader(header)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return header->refCount;
|
||||
}
|
||||
|
||||
uint8_t HMemIsManaged(void *ptr) {
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
return IsValidHeader(header);
|
||||
}
|
||||
|
||||
size_t HMemGetFreeSize(void) {
|
||||
if (!IsReady()) {
|
||||
return 0;
|
||||
}
|
||||
return HTlsfGetFreeSize(&sTlsf);
|
||||
}
|
||||
|
||||
size_t HMemGetUsedSize(void) {
|
||||
if (!IsReady()) {
|
||||
return 0;
|
||||
}
|
||||
return HTlsfGetUsedSize(&sTlsf);
|
||||
}
|
||||
|
||||
size_t HMemGetCapacity(void) {
|
||||
if (!IsReady()) {
|
||||
return 0;
|
||||
}
|
||||
return HTlsfGetCapacity(&sTlsf);
|
||||
}
|
||||
@ -1144,6 +1144,11 @@ size_t HTlsfMinBufferSize(void)
|
||||
return HTlsfControlSize() + sPoolOverhead + sBlockSizeMin + kHTlsfAlignSize - 1;
|
||||
}
|
||||
|
||||
size_t HTlsfMaxBufferSize(void)
|
||||
{
|
||||
return sBlockSizeMax;
|
||||
}
|
||||
|
||||
uint8_t HTlsfInit(HTlsf *htlsf, void *mem, size_t size)
|
||||
{
|
||||
uintptr_t raw;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user