⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpool.c

📁 一个关于memory pool 的实例
💻 C
📖 第 1 页 / 共 3 页
字号:
    size++;  }    /*   * First we check the free lists looking for something with enough   * pages.  Maybe we should only look X bits higher in the list.   *   * XXX: this is where we'd do the best fit.  We'd look for the   * closest match.  We then could put the rest of the allocation that   * we did not use in a lower free list.  Have a define which states   * how deep in the free list to go to find the closest match.   */  for (bit_c = size_to_bits(size); bit_c <= MAX_BITS; bit_c++) {    if (mp_p->mp_free[bit_c] != NULL) {      free_addr = mp_p->mp_free[bit_c];      break;    }  }    /*   * If we haven't allocated any blocks or if the last block doesn't   * have enough memory then we need a new block.   */  if (bit_c > MAX_BITS) {        /* we need to allocate more space */        page_n = PAGES_IN_SIZE(mp_p, size);        /* now we try and get the pages we need/want */    block_p = alloc_pages(mp_p, page_n, error_p);    if (block_p == NULL) {      /* error_p set in alloc_pages */      return NULL;    }        /* init the block header */    block_p->mb_magic = BLOCK_MAGIC;    block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(mp_p, page_n);    block_p->mb_next_p = mp_p->mp_first_p;    block_p->mb_magic2 = BLOCK_MAGIC;        /*     * We insert it into the front of the queue.  We could add it to     * the end but there is not much use.     */    mp_p->mp_first_p = block_p;    if (mp_p->mp_last_p == NULL) {      mp_p->mp_last_p = block_p;    }        free_addr = FIRST_ADDR_IN_BLOCK(block_p);    #ifdef DEBUG    (void)printf("had to allocate space for %lx of %lu bytes\n",		 (long)free_addr, size);#endif    free_end = (char *)free_addr + size;    left = (char *)block_p->mb_bounds_p - (char *)free_end;  }  else {        if (bit_c < min_bit_free_next) {      mp_p->mp_free[bit_c] = NULL;      /* calculate the number of left over bytes */      left = bits_to_size(bit_c) - size;    }    else if (bit_c < min_bit_free_next) {      /* grab the next pointer from the freed address into our list */      memcpy(mp_p->mp_free + bit_c, free_addr, sizeof(void *));      /* calculate the number of left over bytes */      left = bits_to_size(bit_c) - size;    }    else {      /* grab the free structure from the address */      memcpy(&free_pnt, free_addr, sizeof(free_pnt));      mp_p->mp_free[bit_c] = free_pnt.mf_next_p;            /* are we are splitting up a multiblock chunk into fewer blocks? */      if (PAGES_IN_SIZE(mp_p, free_pnt.mf_size) > PAGES_IN_SIZE(mp_p, size)) {	ret = split_block(mp_p, free_addr, size);	if (ret != MPOOL_ERROR_NONE) {	  SET_POINTER(error_p, ret);	  return NULL;	}	/* left over memory was taken care of in split_block */	left = 0;      }      else {	/* calculate the number of left over bytes */	left = free_pnt.mf_size - size;      }    }    #ifdef DEBUG    (void)printf("found a free block at %lx of %lu bytes\n",		 (long)free_addr, left + size);#endif        free_end = (char *)free_addr + size;  }    /*   * If we have memory left over then we free it so someone else can   * use it.  We do not free the space if we just allocated a   * multi-block chunk because we need to have every allocation easily   * find the start of the block.  Every user address % page-size   * should take us to the start of the block.   */  if (left > 0 && size <= MAX_BLOCK_USER_MEMORY(mp_p)) {    /* free the rest of the block */    ret = free_pointer(mp_p, free_end, left);    if (ret != MPOOL_ERROR_NONE) {      SET_POINTER(error_p, ret);      return NULL;    }  }    /* update our bounds */  if (free_addr > mp_p->mp_bounds_p) {    mp_p->mp_bounds_p = free_addr;  }  else if (free_addr < mp_p->mp_min_p) {    mp_p->mp_min_p = free_addr;  }    return free_addr;}/* * static void *alloc_mem * * 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. */static	void	*alloc_mem(mpool_t *mp_p, const unsigned long byte_size,			   int *error_p){  unsigned long	size, fence;  void		*addr;    /* make sure we have enough bytes */  if (byte_size < MIN_ALLOCATION) {    size = MIN_ALLOCATION;  }  else {    size = byte_size;  }    if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {    fence = 0;  }  else {    fence = FENCE_SIZE;  }    /* get our free space + the space for the fence post */  addr = get_space(mp_p, size + fence, error_p);  if (addr == NULL) {    /* error_p set in get_space */    return NULL;  }    if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {    write_magic((char *)addr + size);  }    /* maintain our stats */  mp_p->mp_alloc_c++;  mp_p->mp_user_alloc += size;  if (mp_p->mp_user_alloc > mp_p->mp_max_alloc) {    mp_p->mp_max_alloc = mp_p->mp_user_alloc;  }    SET_POINTER(error_p, MPOOL_ERROR_NONE);  return addr;}/* * static int free_mem * * 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. */static	int	free_mem(mpool_t *mp_p, void *addr, const unsigned long size){  unsigned long	old_size, fence;  int		ret;  mpool_block_t	*block_p;    /*   * If the size is larger than a block then the allocation must be at   * the front of the block.   */  if (size > MAX_BLOCK_USER_MEMORY(mp_p)) {    block_p = (mpool_block_t *)((char *)addr - sizeof(mpool_block_t));    if (block_p->mb_magic != BLOCK_MAGIC	|| block_p->mb_magic2 != BLOCK_MAGIC) {      return MPOOL_ERROR_POOL_OVER;    }  }    /* make sure we have enough bytes */  if (size < MIN_ALLOCATION) {    old_size = MIN_ALLOCATION;  }  else {    old_size = size;  }    /* if we are packing the pool smaller */  if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) {    fence = 0;  }  else {    /* find the user's magic numbers if they were written */    ret = check_magic(addr, old_size);    if (ret != MPOOL_ERROR_NONE) {       return ret;    }    fence = FENCE_SIZE;  }    /* now we free the pointer */  ret = free_pointer(mp_p, addr, old_size + fence);  if (ret != MPOOL_ERROR_NONE) {    return ret;  }  mp_p->mp_user_alloc -= old_size;    /* adjust our stats */  mp_p->mp_alloc_c--;    return MPOOL_ERROR_NONE;}/***************************** exported routines *****************************//* * mpool_t *mpool_open * * DESCRIPTION: * * Open/allocate a new memory pool. * * RETURNS: * * Success - Pool pointer which must be passed to mpool_close to * deallocate. * * Failure - NULL * * ARGUMENTS: * * flags -> Flags to set attributes of the memory pool.  See the top * of mpool.h. * * page_size -> Set the internal memory page-size.  This must be a * multiple of the getpagesize() value.  Set to 0 for the default. * * start_addr -> Starting address to try and allocate memory pools. * This is ignored if the MPOOL_FLAG_USE_SBRK is enabled. * * error_p <- Pointer to integer which, if not NULL, will be set with * a mpool error code. */mpool_t	*mpool_open(const unsigned int flags, const unsigned int page_size,		    void *start_addr, int *error_p){  mpool_block_t	*block_p;  int		page_n, ret;  mpool_t	mp, *mp_p;  void		*free_addr;    if (! enabled_b) {    startup();  }    /* zero our temp struct */  memset(&mp, 0, sizeof(mp));    mp.mp_magic = MPOOL_MAGIC;  mp.mp_flags = flags;  mp.mp_alloc_c = 0;  mp.mp_user_alloc = 0;  mp.mp_max_alloc = 0;  mp.mp_page_c = 0;  /* mp.mp_page_size set below */  /* mp.mp_blocks_bit_n set below */  /* mp.mp_fd set below */  /* mp.mp_top set below */  /* mp.mp_addr set below */  mp.mp_log_func = NULL;  mp.mp_min_p = NULL;  mp.mp_bounds_p = NULL;  mp.mp_first_p = NULL;  mp.mp_last_p = NULL;  mp.mp_magic2 = MPOOL_MAGIC;    /* get and sanity check our page size */  if (page_size > 0) {    mp.mp_page_size = page_size;    if (mp.mp_page_size % getpagesize() != 0) {      SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID);      return NULL;    }  }  else {    mp.mp_page_size = getpagesize() * DEFAULT_PAGE_MULT;    if (mp.mp_page_size % 1024 != 0) {      SET_POINTER(error_p, MPOOL_ERROR_PAGE_SIZE);      return NULL;    }  }    if (BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK)) {    mp.mp_fd = -1;    mp.mp_addr = NULL;    mp.mp_top = 0;  }  else {    /* open dev-zero for our mmaping */    mp.mp_fd = open("/dev/zero", O_RDWR, 0);    if (mp.mp_fd < 0) {      SET_POINTER(error_p, MPOOL_ERROR_OPEN_ZERO);      return NULL;    }    mp.mp_addr = start_addr;    /* we start at the front of the file */    mp.mp_top = 0;  }    /*   * Find out how many pages we need for our mpool structure.   *   * NOTE: this adds possibly unneeded space for mpool_block_t which   * may not be in this block.   */  page_n = PAGES_IN_SIZE(&mp, sizeof(mpool_t));    /* now allocate us space for the actual struct */  mp_p = alloc_pages(&mp, page_n, error_p);  if (mp_p == NULL) {    if (mp.mp_fd >= 0) {      (void)close(mp.mp_fd);      mp.mp_fd = -1;    }    return NULL;  }    /*   * NOTE: we do not normally free the rest of the block here because   * we want to lesson the chance of an allocation overwriting the   * main structure.   */  if (BIT_IS_SET(flags, MPOOL_FLAG_HEAVY_PACKING)) {        /* we add a block header to the front of the block */    block_p = (mpool_block_t *)mp_p;        /* init the block header */    block_p->mb_magic = BLOCK_MAGIC;    block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(&mp, page_n);    block_p->mb_next_p = NULL;    block_p->mb_magic2 = BLOCK_MAGIC;        /* the mpool pointer is then the 2nd thing in the block */    mp_p = FIRST_ADDR_IN_BLOCK(block_p);    free_addr = (char *)mp_p + sizeof(mpool_t);        /* free the rest of the block */    ret = free_pointer(&mp, free_addr,		       (char *)block_p->mb_bounds_p - (char *)free_addr);    if (ret != MPOOL_ERROR_NONE) {      if (mp.mp_fd >= 0) {	(void)close(mp.mp_fd);	mp.mp_fd = -1;      }      /* NOTE: after this line mp_p will be invalid */      (void)free_pages(block_p, SIZE_OF_PAGES(&mp, page_n),		       BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK));      SET_POINTER(error_p, ret);      return NULL;    }        /*     * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool     * header is not on the block linked list.     */        /* now copy our tmp structure into our new memory area */    memcpy(mp_p, &mp, sizeof(mpool_t));        /* we setup min/max to our current address which is as good as any */    mp_p->mp_min_p = block_p;    mp_p->mp_bounds_p = block_p->mb_bounds_p;  }  else {    /* now copy our tmp structure into our new memory area */    memcpy(mp_p, &mp, sizeof(mpool_t));        /* we setup min/max to our current address which is as good as any */    mp_p->mp_min_p = mp_p;    mp_p->mp_bounds_p = (char *)mp_p + SIZE_OF_PAGES(mp_p, page_n);  }    SET_POINTER(error_p, MPOOL_ERROR_NONE);  return mp_p;}/* * int mpool_close * * DESCRIPTION: * * Close/free a memory allocation pool previously opened with * mpool_open. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p <-> Pointer to our memory pool. */int	mpool_close(mpool_t *mp_p){  mpool_block_t	*block_p, *next_p;  void		*addr;  unsigned long	size;  int		ret, final = MPOOL_ERROR_NONE;    /* special case, just return no-error */  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 (mp_p->mp_log_func != NULL) {    mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLOSE, 0, 0, NULL, NULL, 0);  }    /*   * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool   * header is not on the linked list.   */    /* free/invalidate the blocks */  for (block_p = mp_p->mp_first_p; block_p != NULL; block_p = next_p) {    if (block_p->mb_magic != BLOCK_MAGIC	|| block_p->mb_magic2 != BLOCK_MAGIC) {      final = MPOOL_ERROR_POOL_OVER;      break;    }    block_p->mb_magic = 0;    block_p->mb_magic2 = 0;    /* record the next pointer because it might be invalidated below */    next_p = block_p->mb_next_p;    ret = free_pages(block_p, (char *)block_p->mb_bounds_p - (char *)block_p,		     BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK));    if (ret != MPOOL_ERROR_NONE) {      final = ret;    }  }    /* close /dev/zero if necessary */  if (mp_p->mp_fd >= 0) {    (void)close(mp_p->mp_fd);    mp_p->mp_fd = -1;  }    /* invalidate the mpool before we ditch it */  mp_p->mp_magic = 0;  mp_p->mp_magic2 = 0;    /* last we munmap the mpool pointer itself */  if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) {        /* if we are heavy packing then we need to free the 1st block later */    if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) {      addr = (char *)mp_p - sizeof(mpool_block_t);    }    else {      addr = mp_p;    }    size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, sizeof(mpool_t)));        (void)munmap((caddr_t)addr, size);  }    return final;}/* * int mpool_clear * * DESCRIPTION: * * Wipe an opened memory pool clean so we can start again. * * RETURNS: * * Success - MPOOL_ERROR_NONE * * Failure - Mpool error code * * ARGUMENTS: * * mp_p <-> Pointer to our memory pool. */int	mpool_clear(mpool_t *mp_p){  mpool_block_t	*block_p;  int		final = MPOOL_ERROR_NONE, bit_n, ret;  void		*first_p;    /* special case, just return no-error */  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 (mp_p->mp_log_func != NULL) {    mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLEAR, 0, 0, NULL, NULL, 0);  }    /* reset all of our free lists */  for (bit_n = 0; bit_n <= MAX_BITS; bit_n++) {    mp_p->mp_free[bit_n] = NULL;  }    /* free the blocks */  for (block_p = mp_p->mp_first_p;       block_p != NULL;       block_p = block_p->mb_next_p) {    if (block_p->mb_magic != BLOCK_MAGIC	|| block_p->mb_magic2 != BLOCK_MAGIC) {      final = MPOOL_ERROR_POOL_OVER;      break;    }        first_p = FIRST_ADDR_IN_BLOCK(block_p);    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -