XWOS API  4.0
XWOS C/C++ API参考手册
载入中...
搜索中...
未找到
bma.c
浏览该文件的文档.
1
13#include <xwos/standard.h>
14#include <xwos/lib/xwlog.h>
15#include <xwos/lib/bclst.h>
16#include <xwos/lib/xwbop.h>
18#include <xwos/mm/common.h>
19#include <xwos/mm/bma.h>
20
21/* #define XWMM_BMA_LOG */
22#if defined(XWMM_BMA_LOG)
23# define xwmm_bmalogf(lv, fmt, ...) xwlogf(lv, "BMA", fmt, ##__VA_ARGS__)
24#else
25# define xwmm_bmalogf(lv, fmt, ...)
26#endif
27
28static __xwos_code
29struct xwmm_bma_bcb * xwmm_bma_mem_to_bcb(struct xwmm_bma * bma, void * mem);
30
31static __xwos_code
32void * xwmm_bma_bcb_to_mem(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb);
33
34static __xwos_code
35struct xwmm_bma_bcb * xwmm_bma_find_buddy(struct xwmm_bma * bma,
36 struct xwmm_bma_bcb * bcb);
37
38static __xwos_code
39void xwmm_bma_orderlist_add(struct xwmm_bma * bma,
40 struct xwmm_bma_orderlist * ol,
41 xwu8_t odr,
42 struct xwmm_bma_bcb * bcb);
43
44static __xwos_code
46 struct xwmm_bma_orderlist * ol,
47 xwu8_t odr,
48 struct xwmm_bma_bcb * bcb);
49
50static __xwos_code
52 struct xwmm_bma_orderlist * ol);
53
54static __xwos_code
55void xwmm_bma_divide_block(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb,
56 xwsq_t target_odr, struct xwmm_bma_orderlist * curr_ol);
57
58static __xwos_code
59void xwmm_bma_combine(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb);
60
62xwer_t xwmm_bma_init(struct xwmm_bma * bma, const char * name,
63 xwptr_t origin, xwsz_t size,
64 xwsz_t blksize, xwsz_t blkodr)
65{
66 xwer_t rc;
67 xwsz_t num;
68 xwsz_t i;
69
70 XWOS_VALIDATE((bma), "nullptr", -EFAULT);
71
72 num = 1U << blkodr;
73 if (size != (num * blksize)) {
74 rc = -ESIZE;
75 xwmm_bmalogf(ERR, "Size of memory(0x%lX, 0x%lX) is error!\n",
76 origin, size);
77 goto err_size;
78 }
79 bma->name = name;
80 bma->zone.origin = origin;
81 bma->zone.size = blksize * num;
82 bma->blksize = blksize;
83 bma->blkodr = blkodr;
84 xwos_splk_init(&bma->lock);
85 bma->orderlists = (struct xwmm_bma_orderlist *)&bma[(xwsz_t)1];
86 bma->bcbs = (struct xwmm_bma_bcb *)&bma->orderlists[(xwsz_t)1 + blkodr];
87 xwmm_bmalogf(DEBUG,
88 "memory:(0x%lX,0x%lX),orderlists:0x%lX,bcbs:0x%lX,"
89 "blocksize:0x%lX, blockorder:0x%lX\n",
90 origin, size, (xwptr_t)bma->orderlists, (xwptr_t)bma->bcbs,
91 bma->blksize, bma->blkodr);
92
93 for (i = 0; i < num; i++) {
95 }
96 bma->bcbs[0].order = (xwu8_t)blkodr | XWMM_BMA_INUSED;
97
98 for (i = 0; i <= blkodr; i++) {
100 }
101 xwmm_bma_orderlist_add(bma, &bma->orderlists[blkodr], blkodr, &bma->bcbs[0]);
102 return XWOK;
103
104err_size:
105 return rc;
106}
107
114static __xwos_code
115struct xwmm_bma_bcb * xwmm_bma_mem_to_bcb(struct xwmm_bma * bma, void * mem)
116{
117 struct xwmm_bma_bcb * bcb;
118 xwptr_t ofs;
119 xwptr_t idx;
120
121 ofs = (xwptr_t)mem - bma->zone.origin;
122 idx = ofs / (xwptr_t)bma->blksize;
123 if (ofs == (idx * bma->blksize)) {
124 bcb = &bma->bcbs[idx];
125 } else {
126 bcb = err_ptr(-EINVAL);
127 }
128 return bcb;
129}
130
137static __xwos_code
138void * xwmm_bma_bcb_to_mem(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb)
139{
140 xwptr_t idx;
141 xwptr_t mem;
142
143 idx = ((xwptr_t)bcb - (xwptr_t)bma->bcbs) / sizeof(struct xwmm_bma_bcb);
144 mem = (idx * bma->blksize) + bma->zone.origin;
145 return (void *)mem;
146}
147
154static __xwos_code
156 struct xwmm_bma_bcb * bcb)
157{
158 xwsq_t seq;
159 xwsq_t odr;
160
161 seq = ((xwptr_t)bcb - (xwptr_t)bma->bcbs) / sizeof(struct xwmm_bma_bcb);
162 odr = (xwsq_t)bcb->order & XWMM_BMA_ORDER_MASK;
163 seq ^= (1U << odr);
164 return &bma->bcbs[seq];
165}
166
174static __xwos_code
176 struct xwmm_bma_orderlist * ol,
177 xwu8_t odr,
178 struct xwmm_bma_bcb * bcb)
179{
180 struct xwlib_bclst_node * n;
181
182 /* 即将加入的块不在阶链表中,是本地数据。*/
183 if ((XWMM_BMA_INUSED | odr) == bcb->order) {
184 n = xwmm_bma_bcb_to_mem(bma, bcb);
185 xwmm_bmalogf(DEBUG,
186 "[OL:0x%lX][+] bcb(idx:0x%lX,odr:0x%X),mem(0x%lX)\n",
187 (xwptr_t)ol,
188 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
189 sizeof(struct xwmm_bma_bcb)),
190 bcb->order, (xwptr_t)n);
192 xwlib_bclst_add_head(&ol->head, n);
193 /* 当块被加入到阶链表中,就变成共享数据。*/
195 }
196}
197
208static __xwos_code
210 struct xwmm_bma_orderlist * ol,
211 xwu8_t odr,
212 struct xwmm_bma_bcb * bcb)
213{
214 struct xwlib_bclst_node * n;
215 xwer_t rc;
216
217 XWOS_UNUSED(ol);
218 n = xwmm_bma_bcb_to_mem(bma, bcb);
219 xwmm_bmalogf(DEBUG,
220 "[OL:0x%lX][-] bcb(idx:0x%lX,odr:0x%X),mem(0x%lX)\n",
221 (xwptr_t)ol,
222 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
223 sizeof(struct xwmm_bma_bcb)),
224 bcb->order, (xwptr_t)n);
225 /* 即将被删除的块在阶链表中,是共享数据。*/
226 if (odr != bcb->order) {
227 rc = -ESRCH;
228 } else {
230 bcb->order |= XWMM_BMA_INUSED;
231 rc = XWOK;
232 }
233 return rc;
234}
235
243static __xwos_code
245 struct xwmm_bma_orderlist * ol)
246{
247 struct xwlib_bclst_node * n;
248 struct xwmm_bma_bcb * bcb;
249
250 if (xwlib_bclst_tst_empty(&ol->head)) {
251 bcb = err_ptr(-ENOENT);
252 } else {
253 n = ol->head.next;
255 bcb = xwmm_bma_mem_to_bcb(bma, n);
256 xwmm_bmalogf(DEBUG,
257 "[OL:0x%lX][C] bcb(idx:0x%lX,odr:0x%X)\n",
258 (xwptr_t)ol,
259 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
260 sizeof(struct xwmm_bma_bcb)),
261 bcb->order);
262 /* 即将被选择的块在阶链表中,是共享数据。*/
263 bcb->order |= XWMM_BMA_INUSED;
264 }
265 return bcb;
266}
267
275static __xwos_code
276void xwmm_bma_divide_block(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb,
277 xwsq_t target_odr, struct xwmm_bma_orderlist * curr_ol)
278{
279 xwsq_t blk_odr;
280 xwsq_t blk_idx;
281 xwsq_t blk_ofs;
282 struct xwmm_bma_bcb * buddy;
283
284 blk_odr = (xwsq_t)bcb->order & XWMM_BMA_ORDER_MASK;
285 blk_idx = ((xwptr_t)bcb - (xwptr_t)bma->bcbs) / sizeof(struct xwmm_bma_bcb);
286
287 while (blk_odr > target_odr) {
288 curr_ol--;
289 blk_odr--;
290 blk_ofs = 1U << blk_odr;
291 buddy = &bma->bcbs[blk_idx + blk_ofs];
292 /* 加入阶链表之前, `buddy` 是本地数据。*/
294 buddy->order = (xwu8_t)blk_odr | XWMM_BMA_INUSED;
295 xwmm_bma_orderlist_add(bma, curr_ol, blk_odr, buddy);
296 /* `bcb` 是本地数据。*/
297 bcb->order = (xwu8_t)blk_odr | XWMM_BMA_INUSED;
298 xwmm_bmalogf(DEBUG,
299 "[ALLOC][D] bcb(idx:0x%lX,odr:0x%X),"
300 "buddy(idx:0x%lX,odr:0x%X)\n",
301 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
302 sizeof(struct xwmm_bma_bcb)),
303 bcb->order,
304 (((xwptr_t)buddy - (xwptr_t)xwmm_bma->bcbs) /
305 sizeof(struct xwmm_bma_bcb)),
306 buddy->order);
307 }
308}
309
311xwer_t xwmm_bma_alloc(struct xwmm_bma * bma, xwsq_t order, void ** membuf)
312{
313 xwer_t rc;
314 xwreg_t flag;
315 xwsq_t o;
316 struct xwmm_bma_orderlist * ol;
317 struct xwmm_bma_bcb * bcb;
318
319 XWOS_VALIDATE((bma), "nullptr", -EFAULT);
320 XWOS_VALIDATE((membuf), "nullptr", -EFAULT);
321 XWOS_VALIDATE((order <= (xwsq_t)XWSSQ_MAX), "out-of-range", -ERANGE);
322
323 ol = NULL;
324 bcb = err_ptr(-ENOENT);
325 xwos_splk_lock_cpuirqsv(&bma->lock, &flag);
326 for (o = order; o <= bma->blkodr; o++) {
327 ol = &bma->orderlists[o];
328 bcb = xwmm_bma_orderlist_choose(bma, ol);
329 if (!is_err(bcb)) {
330 break;
331 }
332 }
333 if (is_err(bcb)) { // cppcheck-suppress [misra-c2012-14.4]
334 xwos_splk_unlock_cpuirqrs(&bma->lock, flag);
335 rc = -ENOMEM;
336 *membuf = NULL;
337 } else {
338 xwmm_bmalogf(DEBUG,
339 "[ALLOC] bcb(idx:0x%lX,odr:0x%X)\n",
340 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
341 sizeof(struct xwmm_bma_bcb)),
342 bcb->order);
343 xwmm_bma_divide_block(bma, bcb, order, ol);
344 xwos_splk_unlock_cpuirqrs(&bma->lock, flag);
345 rc = XWOK;
346 *membuf = xwmm_bma_bcb_to_mem(bma, bcb);
347 }
348 return rc;
349}
350
357static __xwos_code
358void xwmm_bma_combine(struct xwmm_bma * bma, struct xwmm_bma_bcb * bcb)
359{
360 struct xwmm_bma_bcb * buddy;
361 xwsq_t curr_odr;
362 xwsq_t target_odr;
363 xwer_t rc;
364
365 curr_odr = (bcb->order & XWMM_BMA_ORDER_MASK);
366 target_odr = curr_odr + (xwsq_t)1;
367 while (target_odr <= bma->blkodr) {
368 buddy = xwmm_bma_find_buddy(bma, bcb);
369 xwmm_bmalogf(DEBUG,
370 "[FREE][M] bcb(idx:0x%lX,odr:0x%X),"
371 "buddy(idx:0x%lX,odr:0x%X)\n",
372 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
373 sizeof(struct xwmm_bma_bcb)),
374 bcb->order,
375 (((xwptr_t)buddy - (xwptr_t)xwmm_bma->bcbs) /
376 sizeof(struct xwmm_bma_bcb)),
377 buddy->order);
380 &bma->orderlists[curr_odr],
381 curr_odr,
382 buddy);
383 if (rc < 0) {
384 break;
385 }
386 /* 此时 `buddy->order` 以及 `bcb->order` 都是本地数据。 */
387 if (buddy > bcb) {
389 bcb->order = (xwu8_t)target_odr | XWMM_BMA_INUSED;
390 } else {
392 buddy->order = (xwu8_t)target_odr | XWMM_BMA_INUSED;
393 bcb = buddy;
394 }
395 curr_odr = target_odr;
396 target_odr++;
397 }
398 xwmm_bma_orderlist_add(bma, &bma->orderlists[curr_odr], curr_odr, bcb);
399}
400
402xwer_t xwmm_bma_free(struct xwmm_bma * bma, void * mem)
403{
404 struct xwmm_bma_bcb * bcb;
405 xwreg_t flag;
406 xwer_t rc;
407
408 XWOS_VALIDATE((bma), "nullptr", -EFAULT);
409 XWOS_VALIDATE((mem), "nullptr", -EFAULT);
410
411 if ((((xwptr_t)mem < bma->zone.origin) ||
412 ((xwptr_t)mem >= (bma->zone.origin + bma->zone.size)))) {
413 rc = -ERANGE;
414 goto err_range;
415 }
416 bcb = xwmm_bma_mem_to_bcb(bma, mem);
417 if (is_err(bcb)) { // cppcheck-suppress [misra-c2012-14.4]
418 rc = ptr_err(bcb);
419 goto err_invalmem;
420 }
421 xwmm_bmalogf(DEBUG,
422 "[FREE] mem:0x%lX,bcb(idx:0x%lX,odr:0x%X)\n",
423 (xwptr_t)mem,
424 (((xwptr_t)bcb - (xwptr_t)xwmm_bma->bcbs) /
425 sizeof(struct xwmm_bma_bcb)),
426 bcb->order);
427 if (0 == (XWMM_BMA_INUSED & bcb->order)) {
428 rc = -EINVAL;
429 goto err_invalmem;
430 }
431 xwos_splk_lock_cpuirqsv(&bma->lock, &flag);
432 xwmm_bma_combine(bma, bcb);
433 xwos_splk_unlock_cpuirqrs(&bma->lock, flag);
434 return XWOK;
435
436err_invalmem:
437err_range:
438 return rc;
439}
XWOS通用库:双循环链表
static struct xwmm_bma_bcb * xwmm_bma_mem_to_bcb(struct xwmm_bma *bma, void *mem)
从内存块首地址获得其控制块的指针
Definition bma.c:115
static void xwmm_bma_combine(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
合并内存块
Definition bma.c:358
static void xwmm_bma_orderlist_add(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol, xwu8_t odr, struct xwmm_bma_bcb *bcb)
将一块内存加入到阶链表
Definition bma.c:175
static struct xwmm_bma_bcb * xwmm_bma_orderlist_choose(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol)
从阶链表中选择一块内存,并返回其块控制块
Definition bma.c:244
#define xwmm_bmalogf(lv, fmt,...)
Definition bma.c:25
static struct xwmm_bma_bcb * xwmm_bma_find_buddy(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
寻找内存块的伙伴
Definition bma.c:155
static void * xwmm_bma_bcb_to_mem(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
从内存块的控制块指针获得内存块的首地址
Definition bma.c:138
static xwer_t xwmm_bma_orderlist_remove(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol, xwu8_t odr, struct xwmm_bma_bcb *bcb)
从阶链表中删除一块内存
Definition bma.c:209
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)
将大内存块分割成小块
Definition bma.c:276
XWOS内存管理:伙伴算法内存块分配器
#define XWMM_BMA_ORDER_MASK
Definition bma.h:46
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:初始化伙伴算法内存块分配器
Definition bma.c:62
xwer_t xwmm_bma_free(struct xwmm_bma *bma, void *mem)
XWMM API:释放内存块
Definition bma.c:402
#define XWMM_BMA_INUSED
Definition bma.h:47
#define XWMM_BMA_COMBINED
Definition bma.h:45
xwer_t xwmm_bma_alloc(struct xwmm_bma *bma, xwsq_t order, void **membuf)
XWMM API:申请一块连续的内存
Definition bma.c:311
static void xwlib_bclst_init_head(struct xwlib_bclst_node *h)
初始化一个链表头。
Definition bclst.h:229
static void xwlib_bclst_init_node(struct xwlib_bclst_node *n)
初始化一个链表节点。
Definition bclst.h:240
static bool xwlib_bclst_tst_empty(const struct xwlib_bclst_node *h)
测试链表是否为空。
Definition bclst.h:253
static void xwlib_bclst_add_head(struct xwlib_bclst_node *head, struct xwlib_bclst_node *newn)
将一个节点加入链表头部(链表头的后面)
Definition bclst.h:345
static void xwlib_bclst_del_init(struct xwlib_bclst_node *node)
删除一个节点,并重新初始化它
Definition bclst.h:391
#define __xwos_code
Definition compiler.h:171
#define __xwos_api
Definition compiler.h:175
#define ENOENT
No such file or directory
Definition errno.h:32
#define EINVAL
Invalid argument
Definition errno.h:52
#define EFAULT
Bad address
Definition errno.h:44
#define ESRCH
No such process
Definition errno.h:33
#define ENOMEM
Not enough space
Definition errno.h:42
#define XWOK
No error
Definition errno.h:182
#define ERANGE
Result too large
Definition errno.h:64
#define ESIZE
Size error
Definition errno.h:199
static __xwcc_inline void *__xwcc_must_check err_ptr(xwer_t err)
将错误码转换为指针
Definition error.h:42
static __xwcc_inline bool __xwcc_must_check is_err(const void *ptr)
测试指针的值是否为错误码
Definition error.h:65
static __xwcc_inline xwer_t __xwcc_must_check ptr_err(const void *ptr)
将指针的值转换为错误码
Definition error.h:53
signed long xwer_t
Definition type.h:554
#define NULL
Definition type.h:28
unsigned long xwsz_t
Definition type.h:339
uint8_t xwu8_t
Definition type.h:194
unsigned long xwsq_t
Definition type.h:445
#define XWSSQ_MAX
Definition type.h:473
unsigned long xwptr_t
Definition type.h:375
xwptr_t xwreg_t
Definition type.h:409
static void xwos_splk_unlock_cpuirqrs(struct xwos_splk *spl, xwreg_t cpuirq)
XWOS API:解锁自旋锁,并恢复本地CPU的中断标志
Definition spinlock.h:224
static void xwos_splk_init(struct xwos_splk *spl)
XWOS API:初始化自旋锁
Definition spinlock.h:89
static void xwos_splk_lock_cpuirqsv(struct xwos_splk *spl, xwreg_t *cpuirq)
XWOS API:上锁自旋锁,保存本地CPU的中断标志并关闭
Definition spinlock.h:192
#define XWOS_VALIDATE(exp, errstr,...)
检查函数参数是否有效
Definition standard.h:76
#define XWOS_BUG_ON(x)
Definition standard.h:57
#define XWOS_UNUSED(x)
Definition standard.h:66
操作系统抽象层:自旋锁
双循环链表的节点
Definition bclst.h:27
struct xwlib_bclst_node * next
Definition bclst.h:28
块控制块
Definition bma.h:70
xwu8_t order
Definition bma.h:71
阶链表
Definition bma.h:63
struct xwlib_bclst_node head
Definition bma.h:64
伙伴算法内存块分配器
Definition bma.h:80
struct xwmm_zone zone
Definition bma.h:81
struct xwos_splk lock
Definition bma.h:85
struct xwmm_bma_orderlist * orderlists
Definition bma.h:86
const char * name
Definition bma.h:82
struct xwmm_bma_bcb * bcbs
Definition bma.h:87
xwsq_t blkodr
Definition bma.h:84
xwsz_t blksize
Definition bma.h:83
xwptr_t origin
Definition common.h:41
xwsz_t size
Definition common.h:42
XWOS通用库:位操作
XWOS通用库:日志
XWOS内存管理:通用定义
XWOS的标准头文件