|
| xwer_t | xwmm_bma_init (struct xwmm_bma *bma, const char *name, xwptr_t origin, xwsz_t size, xwsz_t blksize, xwsz_t blkodr) |
| | XWMM API:初始化伙伴算法内存块分配器
|
| |
| xwer_t | xwmm_bma_alloc (struct xwmm_bma *bma, xwsq_t order, void **membuf) |
| | XWMM API:申请一块连续的内存
|
| |
| xwer_t | xwmm_bma_free (struct xwmm_bma *bma, void *mem) |
| | XWMM API:释放内存块
|
| |
| xwer_t | xwmm_bma_malloc (struct xwmm_bma *bma, xwsz_t size, void **membuf) |
| | XWMM API:申请指定大小的连续内存
|
| |
| xwer_t | xwmm_bma_realloc (struct xwmm_bma *bma, xwsz_t size, void **membuf) |
| | XWMM API:调整内存大小
|
| |
| xwer_t | xwmm_bma_memalign (struct xwmm_bma *bma, xwsz_t alignment, xwsz_t size, void **membuf) |
| | XWMM API:申请对齐的内存
|
| |
| xwer_t | xwmm_bma_malloc_usable_size (struct xwmm_bma *bma, void *mem, xwsz_t *size) |
| | XWMM API:返回该块内存实际可用字节数
|
| |
伙伴算法分配器在分配时,会将内存不断地二等分,直到切割到能满足内存的最小尺寸为止。 释放时会检查与之相邻并等长的内存块(称为伙伴)是否空闲, 如果是,就和“伙伴”合并成更大的内存块, 然后继续检测合并后的内存块是否也存在空闲的伙伴,一直向上合并到不能合并为止。
- 优点:
- 支持释放操作;
- 支持大小不固定的内存申请操作;
- 内存碎片的大小只会是单位内存块大小的2的n次方倍,内存碎片更容易被合并。
- 缺点:
- 代码稍微复杂;
- 因为存在合并与切割的循环,申请与释放操作的所需要的时间不是特别稳定;
- 内存大小固定为2的指数,如果申请的内存过小,会造成内存浪费。
- 适用性:对内存复用性要求高的应用场合。
- 上下文的安全性:在任何上下文(中断、中断底半部、线程)都是安全的。
◆ XWMM_BMA_MAX_ORDER
| #define XWMM_BMA_MAX_ORDER ((xwu8_t)126) |
◆ XWMM_BMA_COMBINED
| #define XWMM_BMA_COMBINED ((xwu8_t)127) |
◆ XWMM_BMA_ORDER_MASK
| #define XWMM_BMA_ORDER_MASK ((xwu8_t)0x7F) |
◆ XWMM_BMA_INUSED
| #define XWMM_BMA_INUSED ((xwu8_t)0x80) |
◆ XWMM_BMA_ORDERLIST_SIZE
◆ XWMM_BMA_BCB_SIZE
| #define XWMM_BMA_BCB_SIZE |
( |
|
bo | ) |
sizeof(struct xwmm_bma_bcb[1U << (bo)]) |
◆ XWMM_BMA_RAWOBJ_DEF
| #define XWMM_BMA_RAWOBJ_DEF |
( |
|
name, |
|
|
|
blkodr |
|
) |
| |
值:
#define XWMM_BMA_BCB_SIZE(bo)
#define XWMM_BMA_ORDERLIST_SIZE(bo)
定义伙伴算法内存块分配器结构体的RAW内存空间, 用于初始化伙伴算法内存块分配器结构体
- 参数
-
| [in] | name | 内存数组名 |
| [in] | blkodr | 伙伴算法内存块分配器中单位内存块的数量,以2的blkodr次方形式表示 |
在文件 bma.h 第 58 行定义.
◆ xwmm_bma_init()
XWMM API:初始化伙伴算法内存块分配器
- 参数
-
| [in] | bma | 伙伴算法内存块分配器的指针 |
| [in] | name | 名字 |
| [in] | origin | 内存区域的起始地址 |
| [in] | size | 内存区域的大小 |
| [in] | blksize | 伙伴算法内存块分配器中单位内存块的大小 |
| [in] | blkodr | 伙伴算法内存块分配器中单位内存块的数量,以2的blkodr次方形式表示 |
- 返回
- 错误码
- 返回值
-
- 注解
- 单位内存块的数量只能是2的n次方,即
2, 4, 8, 16, 32, 64, 128, ... ,对应的 blkodr 分别为 1, 2, 3, 4, 5, 6, 7, ... ;
- 内存区域大小必须满足关系:
size == (blksize * (1 << blkodr)) 。
-
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:不可重入
<Size error
< 块正在被使用
< 块已被合并
< 块正在被使用
<No error
在文件 bma.c 第 63 行定义.
66{
70
72
73 num = 1U << blkodr;
74 if (size != (num * blksize)) {
76 xwmm_bmalogf(ERR,
"Size of memory(0x%lX, 0x%lX) is error!\n",
77 origin, size);
78 goto err_size;
79 }
89 "memory:(0x%lX,0x%lX),orderlists:0x%lX,bcbs:0x%lX,"
90 "blocksize:0x%lX, blockorder:0x%lX\n",
93
94 for (i = 0; i < num; i++) {
96 }
98
99 for (i = 0; i <= blkodr; i++) {
101 }
104
105err_size:
106 return rc;
107}
static void xwmm_bma_orderlist_add(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol, xwu8_t odr, struct xwmm_bma_bcb *bcb)
将一块内存加入到阶链表
#define xwmm_bmalogf(lv, fmt,...)
#define XWMM_BMA_COMBINED
static void xwlib_bclst_init_head(struct xwlib_bclst_node *h)
初始化一个链表头。
#define EFAULT
Bad address
static void xwos_splk_init(struct xwos_splk *spl)
XWOS API:初始化自旋锁
#define XWOS_VALIDATE(exp, errstr,...)
检查函数参数是否有效
struct xwlib_bclst_node head
struct xwmm_bma_orderlist * orderlists
struct xwmm_bma_bcb * bcbs
◆ xwmm_bma_alloc()
XWMM API:申请一块连续的内存
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | order | 块数量的阶,内存块大小: ((1 << order) * bma->blksize) |
| [out] | membuf | 指向地址缓存的指针,通过此指针缓存返回申请到的内存的首地址 |
- 返回
- 错误码
- 返回值
-
| -EFAULT | 空指针 |
| -ERANGE | order无效 |
| -ENOMEM | 内存不足 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
<No error
在文件 bma.c 第 312 行定义.
313{
319
323
331 break;
332 }
333 }
338 } else {
340 "[ALLOC] bcb(idx:0x%lX,odr:0x%X)\n",
348 }
349 return rc;
350}
static struct xwmm_bma_bcb * xwmm_bma_orderlist_choose(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol)
从阶链表中选择一块内存,并返回其块控制块
static void * xwmm_bma_bcb_to_mem(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
从内存块的控制块指针获得内存块的首地址
static void xwmm_bma_divide_block(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb, xwsq_t target_odr, struct xwmm_bma_orderlist *curr_ol)
将大内存块分割成小块
#define ENOENT
No such file or directory
#define ENOMEM
Not enough space
#define ERANGE
Result too large
static __xwcc_inline void *__xwcc_must_check err_ptr(xwer_t err)
将错误码转换为指针
static __xwcc_inline bool __xwcc_must_check is_err(const void *ptr)
测试指针的值是否为错误码
static void xwos_splk_unlock_cpuirqrs(struct xwos_splk *spl, xwreg_t cpuirq)
XWOS API:解锁自旋锁,并恢复本地CPU的中断标志
static void xwos_splk_lock_cpuirqsv(struct xwos_splk *spl, xwreg_t *cpuirq)
XWOS API:上锁自旋锁,保存本地CPU的中断标志并关闭
◆ xwmm_bma_free()
XWMM API:释放内存块
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | mem | 内存块的首地址指针 |
- 返回
- 错误码
- 返回值
-
| XWOK | 没有错误 |
| -EINVAL | 参数错误 |
| -ERANGE | 内存块不属于指定的伙伴算法内存块分配器对象 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
< 块正在被使用
<No error
在文件 bma.c 第 403 行定义.
404{
409
412
413 if ((((
xwptr_t)mem < bma->zone.origin) ||
416 goto err_range;
417 }
419 mem = (
void *)((
xwptr_t)mem - unaligned);
423 goto err_invalmem;
424 }
426 "[FREE] mem:0x%lX,bcb(idx:0x%lX,odr:0x%X)\n",
433 goto err_invalmem;
434 }
439
440err_invalmem:
441err_range:
442 return rc;
443}
static struct xwmm_bma_bcb * xwmm_bma_mem_to_bcb(struct xwmm_bma *bma, void *mem)
从内存块首地址获得其控制块的指针
static void xwmm_bma_combine(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
合并内存块
#define EINVAL
Invalid argument
static __xwcc_inline xwer_t __xwcc_must_check ptr_err(const void *ptr)
将指针的值转换为错误码
◆ xwmm_bma_malloc()
XWMM API:申请指定大小的连续内存
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | size | 申请的大小 |
| [out] | membuf | 指向缓冲区的指针,通过此缓冲区返回申请到的内存的首地址 |
- 返回
- 错误码
- 返回值
-
| XWOK | 没有错误 |
| -EFAULT | 空指针 |
| -ENOMEM | 内存不足 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
- 此函数向内存池申请大小为
size 的内存:
- 若申请成功,通过
*membuf 返回申请到的内存地址 ,返回错误码为 XWOK ;
- 若申请失败,通过
*membuf 返回 NULL ,返回值为负的错误码。
- 内存不会被初始化;
- 当
size 为 0 , 通过 *membuf 返回 NULL ,返回错误码为 XWOK ;
<No error
在文件 bma.c 第 446 行定义.
447{
451
454
458 } else {
462 p2++;
463 }
465 }
466 return rc;
467}
xwer_t xwmm_bma_alloc(struct xwmm_bma *bma, xwsq_t order, void **membuf)
XWMM API:申请一块连续的内存
#define XWBOP_DIV_ROUND_UP(n, d)
#define xwbop_fls(type, data)
在数据中从最高位起查找第一个被置1的位
◆ xwmm_bma_realloc()
XWMM API:调整内存大小
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | size | 申请的大小,当size == 0,realloc等价于free |
| [in,out] | membuf | 指向缓冲区的指针,此缓冲区
- (I) 作为输入时,当*membuf == NULL,realloc等价于malloc
- (O) 作为输出时,通过此缓冲区返回申请到的内存的首地址
|
- 返回
- 错误码
- 返回值
-
| XWOK | 没有错误 |
| -EFAULT | 空指针 |
| -ENOMEM | 内存不足 |
| -ERANGE | 内存地址不在内存池的范围内 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
- 此API类似于C11标准中的
realloc() 函数:
- 当
*membuf 为 NULL ,此函数等价于 xwmm_bma_mealloc(mp, size, membuf) ;
- 当
*membuf 不为 NULL 且 size 为 0 , 此函数等价于 xwmm_bma_free(mp, *membuf) ,并且通过 *membuf 返回 NULL ;
- 当
*membuf 不为 NULL 且 size 比之前的小 ,此函数不重新申请内存,直接返回原来的 *membuf 以及 XWOK ;
- 当
*membuf 不为 NULL 且 size 比之前的大 ,此函数会尝试重新申请内存:
- 如果申请失败,原来的内存不会受影响,且通过
*membuf 返回 NULL 以及 错误码;
- 如果申请成功,会将旧内存空间的内容移动到新内存空间内,然后返回新的
*membuf 以及 XWOK 。
<No error
< 阶的掩码
<No error
<No error
在文件 bma.c 第 470 行定义.
471{
476 void * oldm;
477 void * newm;
478
481
482 oldm = *membuf;
485 }
else if ((
xwsz_t)0 == size) {
489 }
490 } else {
491 if ((((
xwptr_t)oldm < bma->zone.origin) ||
494 } else {
497 oldm = (
void *)((
xwptr_t)oldm - unaligned);
500 oldsize = (1U << oldsize);
501 if (size <= oldsize) {
503 } else {
506
507 memcpy(newm, oldm, size);
508 *membuf = newm;
510 } else {
512 }
513 }
514 }
515 }
516 return rc;
517}
#define XWMM_BMA_ORDER_MASK
xwer_t xwmm_bma_free(struct xwmm_bma *bma, void *mem)
XWMM API:释放内存块
xwer_t xwmm_bma_malloc(struct xwmm_bma *bma, xwsz_t size, void **membuf)
XWMM API:申请指定大小的连续内存
◆ xwmm_bma_memalign()
XWMM API:申请对齐的内存
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | alignment | 内存的起始地址对齐的字节数,只能是2的n次方 |
| [in] | size | 申请的大小 |
| [out] | membuf | 指向缓冲区的指针,通过此缓冲区返回申请到的内存的首地址 |
- 返回
- 错误码
- 返回值
-
| XWOK | 没有错误 |
| -EFAULT | 空指针 |
| -ENOMEM | 内存不足 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
- 此API类似于C标准中的
aligned_alloc() 函数:
alignment 如果比 XWMM_ALIGNMENT 小,会被扩大为 XWMM_ALIGNMENT :
alignment 只能是2的n次方:
- 若size小于
alignment , size 会被扩大为 alignment ,
- 若size大于
alignment , size 会向上对齐到2的n次方,此时也一定为 alignment 的整数倍。
- 申请内存失败时,此函数不会修改
*membuf 的值。
< 内存管理对齐的字节数
< 内存管理对齐的字节数
<No error
在文件 bma.c 第 520 行定义.
522{
525
528
531 }
535 goto err_notp2;
536 }
540 goto nothing;
541 }
542
543 if (size <= alignment) {
544 size = alignment;
545 } else {
548 p2++;
549 }
551 }
553
554nothing:
555err_notp2:
556 return rc;
557}
◆ xwmm_bma_malloc_usable_size()
XWMM API:返回该块内存实际可用字节数
- 参数
-
| [in] | bma | 伙伴算法内存块分配器对象的指针 |
| [in] | mem | 内存块的起始地址 |
| [out] | size | 指向缓冲区的指针,通过此缓冲区返回内存快实际大小 |
- 返回
- 错误码
- 返回值
-
| XWOK | 没有错误 |
| -EFAULT | 空指针 |
| -ERANGE | 内存块不在BMA空间 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
- 此API类似于GNUC中的
malloc_usable_size() 函数。
<No error
< 阶的掩码
在文件 bma.c 第 559 行定义.
560{
565
568
569 if ((((
xwptr_t)mem < bma->zone.origin) ||
572 } else {
575 mem = (
void *)((
xwptr_t)mem - unaligned);
578 realsize = (1U << realsize);
579 *size = realsize;
580 }
581 return rc;
582}