📄 mpool.c
字号:
/* free the memory */ ret = free_pointer(mp_p, first_p, MEMORY_IN_BLOCK(block_p)); if (ret != MPOOL_ERROR_NONE) { final = ret; } } return final;}/* * void *mpool_alloc * * DESCRIPTION: * * Allocate space for bytes inside of an already open memory pool. * * RETURNS: * * Success - Pointer to the address to use. * * Failure - NULL * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. If NULL then it will do a * normal malloc. * * byte_size -> Number of bytes to allocate in the pool. Must be >0. * * error_p <- Pointer to integer which, if not NULL, will be set with * a mpool error code. */void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, int *error_p){ void *addr; if (mp_p == NULL) { /* special case -- do a normal malloc */ addr = (void *)malloc(byte_size); if (addr == NULL) { SET_POINTER(error_p, MPOOL_ERROR_ALLOC); return NULL; } else { SET_POINTER(error_p, MPOOL_ERROR_NONE); return addr; } } if (mp_p->mp_magic != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_PNT); return NULL; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); return NULL; } if (byte_size == 0) { SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); return NULL; } addr = alloc_mem(mp_p, byte_size, error_p); if (mp_p->mp_log_func != NULL) { mp_p->mp_log_func(mp_p, MPOOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0); } return addr;}/* * void *mpool_calloc * * DESCRIPTION: * * Allocate space for elements of bytes in the memory pool and zero * the space afterwards. * * RETURNS: * * Success - Pointer to the address to use. * * Failure - NULL * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. If NULL then it will do a * normal calloc. * * ele_n -> Number of elements to allocate. * * ele_size -> Number of bytes per element being allocated. * * error_p <- Pointer to integer which, if not NULL, will be set with * a mpool error code. */void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, const unsigned long ele_size, int *error_p){ void *addr; unsigned long byte_size; if (mp_p == NULL) { /* special case -- do a normal calloc */ addr = (void *)calloc(ele_n, ele_size); if (addr == NULL) { SET_POINTER(error_p, MPOOL_ERROR_ALLOC); return NULL; } else { SET_POINTER(error_p, MPOOL_ERROR_NONE); return addr; } } if (mp_p->mp_magic != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_PNT); return NULL; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); return NULL; } if (ele_n == 0 || ele_size == 0) { SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); return NULL; } byte_size = ele_n * ele_size; addr = alloc_mem(mp_p, byte_size, error_p); if (addr != NULL) { memset(addr, 0, byte_size); } if (mp_p->mp_log_func != NULL) { mp_p->mp_log_func(mp_p, MPOOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0); } /* NOTE: error_p set above */ return addr;}/* * int mpool_free * * DESCRIPTION: * * Free an address from a memory pool. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. If NULL then it will do a * normal free. * * addr <-> Address to free. * * size -> Size of the address being freed. */int mpool_free(mpool_t *mp_p, void *addr, const unsigned long size){ if (mp_p == NULL) { /* special case -- do a normal free */ free(addr); return MPOOL_ERROR_NONE; } if (mp_p->mp_magic != MPOOL_MAGIC) { return MPOOL_ERROR_PNT; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { return MPOOL_ERROR_POOL_OVER; } if (mp_p->mp_log_func != NULL) { mp_p->mp_log_func(mp_p, MPOOL_FUNC_FREE, size, 0, NULL, addr, 0); } if (addr == NULL) { return MPOOL_ERROR_ARG_NULL; } if (size == 0) { return MPOOL_ERROR_ARG_INVALID; } return free_mem(mp_p, addr, size);}/* * void *mpool_resize * * DESCRIPTION: * * Reallocate an address in a mmeory pool to a new size. This is * different from realloc in that it needs the old address' size. If * you don't have it then you need to allocate new space, copy the * data, and free the old pointer yourself. * * RETURNS: * * Success - Pointer to the address to use. * * Failure - NULL * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. If NULL then it will do a * normal realloc. * * old_addr -> Previously allocated address. * * old_byte_size -> Size of the old address. Must be known, cannot be * 0. * * new_byte_size -> New size of the allocation. * * error_p <- Pointer to integer which, if not NULL, will be set with * a mpool error code. */void *mpool_resize(mpool_t *mp_p, void *old_addr, const unsigned long old_byte_size, const unsigned long new_byte_size, int *error_p){ unsigned long copy_size, new_size, old_size, fence; void *new_addr; mpool_block_t *block_p; int ret; if (mp_p == NULL) { /* special case -- do a normal realloc */ new_addr = (void *)realloc(old_addr, new_byte_size); if (new_addr == NULL) { SET_POINTER(error_p, MPOOL_ERROR_ALLOC); return NULL; } else { SET_POINTER(error_p, MPOOL_ERROR_NONE); return new_addr; } } if (mp_p->mp_magic != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_PNT); return NULL; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); return NULL; } if (old_addr == NULL) { SET_POINTER(error_p, MPOOL_ERROR_ARG_NULL); return NULL; } if (old_byte_size == 0) { SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); return NULL; } /* * If the size is larger than a block then the allocation must be at * the front of the block. */ if (old_byte_size > MAX_BLOCK_USER_MEMORY(mp_p)) { block_p = (mpool_block_t *)((char *)old_addr - sizeof(mpool_block_t)); if (block_p->mb_magic != BLOCK_MAGIC || block_p->mb_magic2 != BLOCK_MAGIC) { SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); return NULL; } } /* make sure we have enough bytes */ if (old_byte_size < MIN_ALLOCATION) { old_size = MIN_ALLOCATION; } else { old_size = old_byte_size; } /* verify that the size matches exactly if we can */ if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { fence = 0; } else if (old_size > 0) { ret = check_magic(old_addr, old_size); if (ret != MPOOL_ERROR_NONE) { SET_POINTER(error_p, ret); return NULL; } fence = FENCE_SIZE; } /* make sure we have enough bytes */ if (new_byte_size < MIN_ALLOCATION) { new_size = MIN_ALLOCATION; } else { new_size = new_byte_size; } /* * NOTE: we could here see if the size is the same or less and then * use the current memory and free the space above. This is harder * than it sounds if we are changing the block size of the * allocation. */ /* we need to get another address */ new_addr = alloc_mem(mp_p, new_byte_size, error_p); if (new_addr == NULL) { /* error_p set in mpool_alloc */ return NULL; } if (new_byte_size > old_byte_size) { copy_size = old_byte_size; } else { copy_size = new_byte_size; } memcpy(new_addr, old_addr, copy_size); /* free the old address */ ret = free_mem(mp_p, old_addr, old_byte_size); if (ret != MPOOL_ERROR_NONE) { /* if the old free failed, try and free the new address */ (void)free_mem(mp_p, new_addr, new_byte_size); SET_POINTER(error_p, ret); return NULL; } if (mp_p->mp_log_func != NULL) { mp_p->mp_log_func(mp_p, MPOOL_FUNC_RESIZE, new_byte_size, 0, new_addr, old_addr, old_byte_size); } SET_POINTER(error_p, MPOOL_ERROR_NONE); return new_addr;}/* * int mpool_stats * * DESCRIPTION: * * Return stats from the memory pool. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p -> Pointer to the memory pool. * * page_size_p <- Pointer to an unsigned integer which, if not NULL, * will be set to the page-size of the pool. * * num_alloced_p <- Pointer to an unsigned long which, if not NULL, * will be set to the number of pointers currently allocated in pool. * * user_alloced_p <- Pointer to an unsigned long which, if not NULL, * will be set to the number of user bytes allocated in this pool. * * max_alloced_p <- Pointer to an unsigned long which, if not NULL, * will be set to the maximum number of user bytes that have been * allocated in this pool. * * tot_alloced_p <- Pointer to an unsigned long which, if not NULL, * will be set to the total amount of space (including administrative * overhead) used by the pool. */int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, unsigned long *num_alloced_p, unsigned long *user_alloced_p, unsigned long *max_alloced_p, unsigned long *tot_alloced_p){ if (mp_p == NULL) { return MPOOL_ERROR_ARG_NULL; } if (mp_p->mp_magic != MPOOL_MAGIC) { return MPOOL_ERROR_PNT; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { return MPOOL_ERROR_POOL_OVER; } SET_POINTER(page_size_p, mp_p->mp_page_size); SET_POINTER(num_alloced_p, mp_p->mp_alloc_c); SET_POINTER(user_alloced_p, mp_p->mp_user_alloc); SET_POINTER(max_alloced_p, mp_p->mp_max_alloc); SET_POINTER(tot_alloced_p, SIZE_OF_PAGES(mp_p, mp_p->mp_page_c)); return MPOOL_ERROR_NONE;}/* * int mpool_set_log_func * * DESCRIPTION: * * Set a logging callback function to be called whenever there was a * memory transaction. See mpool_log_func_t. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. * * log_func -> Log function (defined in mpool.h) which will be called * with each mpool transaction. */int mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func){ if (mp_p == NULL) { return MPOOL_ERROR_ARG_NULL; } if (mp_p->mp_magic != MPOOL_MAGIC) { return MPOOL_ERROR_PNT; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { return MPOOL_ERROR_POOL_OVER; } mp_p->mp_log_func = log_func; return MPOOL_ERROR_NONE;}/* * int mpool_set_max_pages * * DESCRIPTION: * * Set the maximum number of pages that the library will use. Once it * hits the limit it will return MPOOL_ERROR_NO_PAGES. * * NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages * value will include the page with the mpool header structure in it. * If the flag is _not_ set then the max-pages will not include this * first page. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p <-> Pointer to the memory pool. * * max_pages -> Maximum number of pages used by the library. */int mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages){ if (mp_p == NULL) { return MPOOL_ERROR_ARG_NULL; } if (mp_p->mp_magic != MPOOL_MAGIC) { return MPOOL_ERROR_PNT; } if (mp_p->mp_magic2 != MPOOL_MAGIC) { return MPOOL_ERROR_POOL_OVER; } if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) { mp_p->mp_max_pages = max_pages; } else { /* * If we are not heavy-packing the pool then we don't count the * 1st page allocated which holds the mpool header structure. */ mp_p->mp_max_pages = max_pages + 1; } return MPOOL_ERROR_NONE;}/* * const char *mpool_strerror * * DESCRIPTION: * * Return the corresponding string for the error number. * * RETURNS: * * Success - String equivalient of the error. * * Failure - String "invalid error code" * * ARGUMENTS: * * error -> Error number that we are converting. */const char *mpool_strerror(const int error){ switch (error) { case MPOOL_ERROR_NONE: return "no error"; break; case MPOOL_ERROR_ARG_NULL: return "function argument is null"; break; case MPOOL_ERROR_ARG_INVALID: return "function argument is invalid"; break; case MPOOL_ERROR_PNT: return "invalid mpool pointer"; break; case MPOOL_ERROR_POOL_OVER: return "mpool structure was overwritten"; break; case MPOOL_ERROR_PAGE_SIZE: return "could not get system page-size"; break; case MPOOL_ERROR_OPEN_ZERO: return "could not open /dev/zero"; break; case MPOOL_ERROR_NO_MEM: return "no memory available"; break; case MPOOL_ERROR_MMAP: return "problems with mmap"; break; case MPOOL_ERROR_SIZE: return "error processing requested size"; break; case MPOOL_ERROR_TOO_BIG: return "allocation exceeds pool max size"; break; case MPOOL_ERROR_MEM: return "invalid memory address"; break; case MPOOL_ERROR_MEM_OVER: return "memory lower bounds overwritten"; break; case MPOOL_ERROR_NOT_FOUND: return "memory block not found in pool"; break; case MPOOL_ERROR_IS_FREE: return "memory address has already been freed"; break; case MPOOL_ERROR_BLOCK_STAT: return "invalid internal block status"; break; case MPOOL_ERROR_FREE_ADDR: return "invalid internal free address"; break; case MPOOL_ERROR_SBRK_CONTIG: return "sbrk did not return contiguous memory"; break; case MPOOL_ERROR_NO_PAGES: return "no available pages left in pool"; break; case MPOOL_ERROR_ALLOC: return "system alloc function failed"; break; case MPOOL_ERROR_PNT_OVER: return "user pointer admin space overwritten"; break; default: break; } return "invalid error code";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -