void mem_put (struct mem_pool *pool, void *ptr) { struct list_head *list = NULL; int *in_use = NULL; void *head = NULL; if (!pool || !ptr) { gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); return; } LOCK (&pool->lock); { switch (__is_member (pool, ptr)) { case 1: list = head = mem_pool_ptr2chunkhead (ptr); in_use = (head + GF_MEM_POOL_LIST_BOUNDARY); if (!is_mem_chunk_in_use(in_use)) { gf_log_callingfn ("mem-pool", GF_LOG_CRITICAL, "mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); break; } pool->hot_count--; pool->cold_count++; *in_use = 0; list_add (list, &pool->list); break; case -1: /* For some reason, the address given is within * the address range of the mem-pool but does not align * with the expected start of a chunk that includes * the list headers also. Sounds like a problem in * layers of clouds up above us. ;) */ abort (); break; case 0: /* The address is outside the range of the mem-pool. We * assume here that this address was allocated at a * point when the mem-pool was out of chunks in mem_get * or the programmer has made a mistake by calling the * wrong de-allocation interface. We do * not have enough info to distinguish between the two * situations. */ FREE (ptr); break; default: /* log error */ break; } } UNLOCK (&pool->lock); }
static int __is_member (struct mem_pool *pool, void *ptr) { if (!pool || !ptr) { gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return -1; } if (ptr < pool->pool || ptr >= pool->pool_end) return 0; if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) % pool->padded_sizeof_type) return -1; return 1; }
/*当我们使用完一个内存池中的内存结构以后就需要还给内存池以便被以后的程序使用, 达到循环使用的目的。但是在归还以前我们首先需要判断是不是内存池对象的一个成员, 判断的结果有三种,分别是:是,不是和错误情况(就是它在内存池的内存范围以内, 但是不符合内存池对象的大小),实现如下*/ static int __is_member (struct mem_pool *pool, void *ptr) //判断ptr指向的内存是否是pool的成员 { if (!pool || !ptr) { gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return -1; } if (ptr < pool->pool || ptr >= pool->pool_end) //ptr如果不再pool开始到结束的范围内就不是 return 0; if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) % pool->padded_sizeof_type)//判断是否是一个符合内存块大小的内存对象 return -1; return 1; }
void mem_put (void *ptr) { struct list_head *list = NULL; int *in_use = NULL; void *head = NULL; struct mem_pool **tmp = NULL; struct mem_pool *pool = NULL; if (!ptr) { gf_msg_callingfn ("mem-pool", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "invalid argument"); return; } list = head = mem_pool_ptr2chunkhead (ptr); tmp = mem_pool_from_ptr (head); if (!tmp) { gf_msg_callingfn ("mem-pool", GF_LOG_ERROR, 0, LG_MSG_PTR_HEADER_CORRUPTED, "ptr header is corrupted"); return; } pool = *tmp; if (!pool) { gf_msg_callingfn ("mem-pool", GF_LOG_ERROR, 0, LG_MSG_MEMPOOL_PTR_NULL, "mem-pool ptr is NULL"); return; } LOCK (&pool->lock); { switch (__is_member (pool, ptr)) { case 1: in_use = (head + GF_MEM_POOL_LIST_BOUNDARY + GF_MEM_POOL_PTR); if (!is_mem_chunk_in_use(in_use)) { gf_msg_callingfn ("mem-pool", GF_LOG_CRITICAL, 0, LG_MSG_MEMPOOL_INVALID_FREE, "mem_put called on freed ptr" " %p of mem pool %p", ptr, pool); break; } pool->hot_count--; pool->cold_count++; *in_use = 0; list_add (list, &pool->list); break; case -1: /* For some reason, the address given is within * the address range of the mem-pool but does not align * with the expected start of a chunk that includes * the list headers also. Sounds like a problem in * layers of clouds up above us. ;) */ abort (); break; case 0: /* The address is outside the range of the mem-pool. We * assume here that this address was allocated at a * point when the mem-pool was out of chunks in mem_get * or the programmer has made a mistake by calling the * wrong de-allocation interface. We do * not have enough info to distinguish between the two * situations. */ pool->curr_stdalloc--; GF_FREE (list); break; default: /* log error */ break; } } UNLOCK (&pool->lock); }