内存池设计是嵌入式系统的一个重要环节,之前我们也讨论过相关的内容。但是,看了rawos的代码之后,我觉得rawos的内存池设计更有特点。整个内存池的设计非常健壮,不但考虑了字节对齐的问题,而且还引入了等待调度机制,这是我所没有想到的。所以,在此我很愿意和大家分享这份的代码。闲话不多说,我们看看rawos的mempool数据结构是什么样的,
typedef struct MEM_POOL { RAW_COMMON_BLOCK_OBJECT common_block_obj; /* Define the number of available memory blocks in the pool. */ RAW_U32 raw_block_pool_available; /* Define the head pointer of the available block pool. */ RAW_U8 *raw_block_pool_available_list; } MEM_POOL;
内存池的结构非常简单,主要包括了通用阻塞结构、block数值,block起始指针。内存池下面可以包括若干个block,每个block的大小都是相等的,同时block之间是通过链表串联在一起的,这个我们看了后面的代码明白了。mempool的处理函数不多,三个,初始化、申请、释放函数。
RAW_U16 raw_block_pool_create(MEM_POOL *pool_ptr, RAW_U8 *name_ptr, RAW_U32 block_size, RAW_VOID *pool_start, RAW_U32 pool_size) { //MEM_POOL *tail_ptr; /* Working block pool pointer */ RAW_U32 blocks; /* Number of blocks in pool */ RAW_U8 *block_ptr; /* Working block pointer */ RAW_U8 *next_block_ptr; /* Next block pointer */ RAW_U8 *end_of_pool; /* End of pool area */ RAW_U8 block_align_mask; #if (RAW_BLOCK_FUNCTION_CHECK > 0) /* Check for invalid pool size. */ if (pool_size < (block_size + block_size) ) { return RAW_BLOCK_SIZE_ERROR; } if (pool_ptr == 0) { return RAW_NULL_OBJECT; } if (pool_start == 0) { return RAW_NULL_POINTER; } #endif block_align_mask = sizeof(void *) - 1u; if (((RAW_U32)pool_start & block_align_mask)){ return RAW_INVALID_ALIGN; } if ((pool_size & block_align_mask)) { return RAW_INVALID_ALIGN; } if ((block_size & block_align_mask)) { return RAW_INVALID_ALIGN; } /*Init the list*/ list_init(&pool_ptr->common_block_obj.block_list); /* Setup the basic block pool fields. */ pool_ptr ->common_block_obj.name = name_ptr; pool_ptr ->common_block_obj.block_way = 0; /* Calculate the end of the pool's memory area. */ end_of_pool = (RAW_U8 *) pool_start + pool_size; /* Walk through the pool area, setting up the available block list. */ blocks = 0; block_ptr = (RAW_U8 *) pool_start; next_block_ptr = block_ptr + block_size; while (next_block_ptr <= end_of_pool) { blocks++; if (next_block_ptr == end_of_pool) { break; } /* Setup the link to the next block. */ *((RAW_U8 * *) block_ptr) = next_block_ptr; /* Advance to the next block. */ block_ptr = next_block_ptr; /* Update the next block pointer. */ next_block_ptr = block_ptr + block_size; } /* Set the last block's forward pointer to NULL. */ *((RAW_U8 * *) block_ptr) = 0; /* Save the remaining information in the pool control block. */ pool_ptr ->raw_block_pool_available = blocks; pool_ptr ->raw_block_pool_available_list = (RAW_U8 *) pool_start; return RAW_SUCCESS; }