GlusterFS源碼解析 —— GlusterFS 內存分配方式

原文地址:http://blog.csdn.net/wangyuling1234567890/article/details/24564891


GlusterFS 的內存分配主要有兩種方式,一種是內存池分配,一種是普通內存分配。

不瞭解內存池使用的請查閱相關資料,這裏不再解釋。

內存池分配使用一個mem_pool對象來管理,看過內核代碼的話對內存池的結構就不會陌生了。內核代碼中好多管理就是利用內核list鏈表來進行。內存池結構如下:

struct mem_pool {
        struct list_head  list;              //內存池中未使用內存塊鏈表
        int               hot_count;         //內存池中已經使用內存塊數量
        int               cold_count;        //內存池中剩餘未使用內存塊數量
        gf_lock_t         lock;
        unsigned long     padded_sizeof_type;//內存池中每個塊實際佔用內存大小
        void             *pool;              //內存池中第一個可用內存塊地址
        void             *pool_end;          //內存池中最後一個可用內存塊地址
        int               real_sizeof_type;  //內存池中每個塊可用內存大小
        uint64_t          alloc_count;       //內存池總申請次數:申請到次數 + 未申請到內存塊次數
        uint64_t          pool_misses;       //內存池申請內存塊失敗次數
        int               max_alloc;
        int               curr_stdalloc;     //內存池申請內存塊失敗,重新從系統申請內存塊個數。內存釋放時該值減一
        int               max_stdalloc;      
        char             *name;              //內存池名稱
        struct list_head  global_list;       //用來掛在全局內存池鏈表 THIS->ctx->mempool_list 上
};

看內存分配的代碼時,如果瞭解了GlusterFS內存分配結構,就沒有什麼難度了。其內存分配機構如下:

內存池中每個內存塊結構:


普通內存分配結構(申請N字節內存時實際申請內存結構):


Mem-pool.h

/*
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
  This file is part of GlusterFS.

  This file is licensed to you under your choice of the GNU Lesser
  General Public License, version 3 or any later version (LGPLv3 or
  later), or the GNU General Public License, version 2 (GPLv2), in all
  cases as published by the Free Software Foundation.
*/

#ifndef _MEM_POOL_H_
#define _MEM_POOL_H_

#include "list.h"
#include "locking.h"
#include "logging.h"
#include "mem-types.h"
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <stdarg.h>


struct mem_acct {
        uint32_t            num_types;
        struct mem_acct_rec     *rec;
};

struct mem_acct_rec {
        size_t          size;
        size_t          max_size;
        uint32_t        num_allocs;
        uint32_t        total_allocs;
        uint32_t        max_num_allocs;
        gf_lock_t       lock;
};


void *
__gf_calloc (size_t cnt, size_t size, uint32_t type);

void *
__gf_malloc (size_t size, uint32_t type);

void *
__gf_realloc (void *ptr, size_t size);

int
gf_vasprintf (char **string_ptr, const char *format, va_list arg);

int
gf_asprintf (char **string_ptr, const char *format, ...);

void
__gf_free (void *ptr);


static inline
void* __gf_default_malloc (size_t size)
{
        void *ptr = NULL;

        ptr = malloc (size);
        if (!ptr)
                gf_log_nomem ("", GF_LOG_ALERT, size);

        return ptr;
}

static inline
void* __gf_default_calloc (int cnt, size_t size)
{
        void *ptr = NULL;

        ptr = calloc (cnt, size);  /* 在堆上分配cnt個size大小空間,並初始化爲0 */
        if (!ptr)
                gf_log_nomem ("", GF_LOG_ALERT, (cnt * size));

        return ptr;
}

static inline
void* __gf_default_realloc (void *oldptr, size_t size)
{
        void *ptr = NULL;

        ptr = realloc (oldptr, size);
        if (!ptr)
                gf_log_nomem ("", GF_LOG_ALERT, size);

        return ptr;
}

#define MALLOC(size)       __gf_default_malloc(size)
#define CALLOC(cnt,size)   __gf_default_calloc(cnt,size)
#define REALLOC(ptr,size)  __gf_default_realloc(ptr,size)

/* 指針賦值0xeeeeeeee是什麼意思 ???? */
#define FREE(ptr)                               \
        if (ptr != NULL) {                      \
                free ((void *)ptr);             \
                ptr = (void *)0xeeeeeeee;       \
        }

#define GF_CALLOC(nmemb, size, type) __gf_calloc (nmemb, size, type)

#define GF_MALLOC(size, type)  __gf_malloc (size, type)

#define GF_REALLOC(ptr, size)  __gf_realloc (ptr, size)

#define GF_FREE(free_ptr) __gf_free (free_ptr)

static inline
char *gf_strndup (const char *src, size_t len)
{
        char *dup_str = NULL;

        if (!src) {
                goto out;
        }

        dup_str = GF_CALLOC (1, len + 1, gf_common_mt_strdup);
        if (!dup_str) {
                goto out;
        }

        memcpy (dup_str, src, len);
out:
        return dup_str;
}

static inline
char * gf_strdup (const char *src)
{

        char    *dup_str = NULL;
        size_t  len = 0;

        len = strlen (src) + 1;

        dup_str = GF_CALLOC(1, len, gf_common_mt_strdup);

        if (!dup_str)
                return NULL;

        memcpy (dup_str, src, len);

        return dup_str;
}

static inline void *
gf_memdup (const void *src, void *dst, size_t size)
{
        void *dup_mem = NULL;

        dup_mem = GF_CALLOC(1, size, gf_common_mt_strdup);
        if (!dup_mem)
                goto out;

        memcpy (dup_mem, src, size);

out:
        return dup_mem;
}

struct mem_pool {
        struct list_head  list;              //內存池中未使用內存塊鏈表
        int               hot_count;         //內存池中已經使用內存塊數量
        int               cold_count;        //內存池中剩餘未使用內存塊數量
        gf_lock_t         lock;
        unsigned long     padded_sizeof_type;//內存池中每個塊實際佔用內存大小
        void             *pool;              //內存池中第一個可用內存塊地址
        void             *pool_end;          //內存池中最後一個可用內存塊地址
        int               real_sizeof_type;  //內存池中每個塊可用內存大小
        uint64_t          alloc_count;       //內存池總申請次數:申請到次數 + 未申請到內存塊次數
        uint64_t          pool_misses;       //內存池申請內存塊失敗次數
        int               max_alloc;
        int               curr_stdalloc;     //內存池申請內存塊失敗,重新從系統申請內存塊個數。內存釋放時該值減一
        int               max_stdalloc;      
        char             *name;              //內存池名稱
        struct list_head  global_list;       //用來掛在全局內存池鏈表 THIS->ctx->mempool_list 上
};

struct mem_pool *
mem_pool_new_fn (unsigned long sizeof_type, unsigned long count, char *name);

#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type)

void mem_put (void *ptr);
void *mem_get (struct mem_pool *pool);
void *mem_get0 (struct mem_pool *pool);

void mem_pool_destroy (struct mem_pool *pool);

void gf_mem_acct_enable_set (void *ctx);

#endif /* _MEM_POOL_H */

Mem-pool.c

/*
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
  This file is part of GlusterFS.

  This file is licensed to you under your choice of the GNU Lesser
  General Public License, version 3 or any later version (LGPLv3 or
  later), or the GNU General Public License, version 2 (GPLv2), in all
  cases as published by the Free Software Foundation.
*/

#include "mem-pool.h"
#include "logging.h"
#include "xlator.h"
#include <stdlib.h>
#include <stdarg.h>

/*
 * gf mem_pool 中內存塊申請內存結構: 
  {
    struct list_head;
    struct mem_pool*;
    int in_use;        //該內存塊是否被使用: 1表示被使用, 0表示未使用
    char mem_size[N];  //實際可供使用的內存大小
  }
 *
 * 每次內存池申請 mem_size 大小的內存,gf方式申請都會申請上面一個結構體大小的內存。
 */
 
#define GF_MEM_POOL_LIST_BOUNDARY        (sizeof(struct list_head))
#define GF_MEM_POOL_PTR                  (sizeof(struct mem_pool*))
#define GF_MEM_POOL_PAD_BOUNDARY         (GF_MEM_POOL_LIST_BOUNDARY  + GF_MEM_POOL_PTR + sizeof(int))
#define mem_pool_chunkhead2ptr(head)     ((head) + GF_MEM_POOL_PAD_BOUNDARY)
#define mem_pool_ptr2chunkhead(ptr)      ((ptr) - GF_MEM_POOL_PAD_BOUNDARY)
#define is_mem_chunk_in_use(ptr)         (*ptr == 1)
#define mem_pool_from_ptr(ptr)           ((ptr) + GF_MEM_POOL_LIST_BOUNDARY)

/*
 * __gf_*alloc: 普通 內存申請結構: 
  {
    GF_MEM_HEADER_SIZE;    //4 + sizeof (size_t) + sizeof (xlator_t *)    + 4          +        8
                             4 + mem_size 大小N  + xlator_t指針   + GF_MEM_HEADER_MAGIC +     
    GF_MEM_TRAILER_SIZE;   //8字節

    char mem_size[N];      //實際可供使用的內存大小
    char mem_end[GF_MEM_TRAILER_SIZE]; // 8字節,填充魔術字 0xBAADF00D,標誌內存結尾
  }
 *
 * 每次申請 mem_size 大小的內存,都會申請上面一個結構體大小的內存。
 */
#define GF_MEM_HEADER_SIZE  (4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8)
#define GF_MEM_TRAILER_SIZE 8

/* 這些魔術字表示什麼意思 ??? */
#define GF_MEM_HEADER_MAGIC  0xCAFEBABE
#define GF_MEM_TRAILER_MAGIC 0xBAADF00D

#define GLUSTERFS_ENV_MEM_ACCT_STR  "GLUSTERFS_DISABLE_MEM_ACCT"

void
gf_mem_acct_enable_set (void *data)
{
        glusterfs_ctx_t *ctx = NULL;

        ctx = data;

        GF_ASSERT (ctx);

        ctx->mem_acct_enable = 1;

        return;
}

void
gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr,
                      size_t size, uint32_t type)
{
        char    *ptr = NULL;

        if (!alloc_ptr)
                return;

        ptr = (char *) (*alloc_ptr);

        GF_ASSERT (xl != NULL);

        GF_ASSERT (xl->mem_acct.rec != NULL);

        GF_ASSERT (type <= xl->mem_acct.num_types);

        LOCK(&xl->mem_acct.rec[type].lock);
        {
                xl->mem_acct.rec[type].size += size;
                xl->mem_acct.rec[type].num_allocs++;
                xl->mem_acct.rec[type].total_allocs++;
                xl->mem_acct.rec[type].max_size =
                        max (xl->mem_acct.rec[type].max_size,
                             xl->mem_acct.rec[type].size);
                xl->mem_acct.rec[type].max_num_allocs =
                        max (xl->mem_acct.rec[type].max_num_allocs,
                             xl->mem_acct.rec[type].num_allocs);
        }
        UNLOCK(&xl->mem_acct.rec[type].lock);

        *(uint32_t *)(ptr) = type;
        ptr = ptr + 4;
        memcpy (ptr, &size, sizeof(size_t));
        ptr += sizeof (size_t);
        memcpy (ptr, &xl, sizeof(xlator_t *));
        ptr += sizeof (xlator_t *);
        *(uint32_t *)(ptr) = GF_MEM_HEADER_MAGIC;
        ptr = ptr + 4;
        ptr = ptr + 8; //padding
        *(uint32_t *) (ptr + size) = GF_MEM_TRAILER_MAGIC;

        *alloc_ptr = (void *)ptr;
        return;
}


void *
__gf_calloc (size_t nmemb, size_t size, uint32_t type)
{
        size_t          tot_size = 0;
        size_t          req_size = 0;
        char            *ptr = NULL;
        xlator_t        *xl = NULL;

        if (!THIS->ctx->mem_acct_enable)
                return CALLOC (nmemb, size);

        xl = THIS;

        req_size = nmemb * size;
        tot_size = req_size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE;

        ptr = calloc (1, tot_size);

        if (!ptr) {
                gf_log_nomem ("", GF_LOG_ALERT, tot_size);
                return NULL;
        }
        gf_mem_set_acct_info (xl, &ptr, req_size, type);

        return (void *)ptr;
}

void *
__gf_malloc (size_t size, uint32_t type)
{
        size_t          tot_size = 0;
        char            *ptr = NULL;
        xlator_t        *xl = NULL;

        if (!THIS->ctx->mem_acct_enable)
                return MALLOC (size);

        xl = THIS;

        tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE;

        ptr = malloc (tot_size);
        if (!ptr) {
                gf_log_nomem ("", GF_LOG_ALERT, tot_size);
                return NULL;
        }
        gf_mem_set_acct_info (xl, &ptr, size, type);

        return (void *)ptr;
}

void *
__gf_realloc (void *ptr, size_t size)
{
        size_t          tot_size = 0;
        char            *orig_ptr = NULL;
        xlator_t        *xl = NULL;
        uint32_t        type = 0;

        if (!THIS->ctx->mem_acct_enable)
                return REALLOC (ptr, size);

        tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE;

        orig_ptr = (char *)ptr - 8 - 4;

        GF_ASSERT (*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC);

        orig_ptr = orig_ptr - sizeof(xlator_t *);
        xl = *((xlator_t **)orig_ptr);

        orig_ptr = (char *)ptr - GF_MEM_HEADER_SIZE;
        type = *(uint32_t *)orig_ptr;

        ptr = realloc (orig_ptr, tot_size);
        if (!ptr) {
                gf_log_nomem ("", GF_LOG_ALERT, tot_size);
                return NULL;
        }

        gf_mem_set_acct_info (xl, (char **)&ptr, size, type);

        return (void *)ptr;
}

/*
 * 把參數列表解析到出參 string_ptr 中,並返回字符串長度
 *
 * 注意:自動爲出參分配內存
 */
int
gf_vasprintf (char **string_ptr, const char *format, va_list arg)
{
        va_list arg_save;
        char    *str = NULL;
        int     size = 0;
        int     rv = 0;

        if (!string_ptr || !format)
                return -1;

        va_copy (arg_save, arg);

        size = vsnprintf (NULL, 0, format, arg);
        size++;
        str = GF_MALLOC (size, gf_common_mt_asprintf);
        if (str == NULL) {
                /* log is done in GF_MALLOC itself */
                return -1;
        }
        rv = vsnprintf (str, size, format, arg_save);

        *string_ptr = str;
        return (rv);
}

/* 
 * 爲出參string_ptr分配內存,並把變參內容格式化存放在string_ptr中
 *
 * 返回出參長度
 */
int
gf_asprintf (char **string_ptr, const char *format, ...)
{
        va_list arg;
        int     rv = 0;

        va_start (arg, format);
        rv = gf_vasprintf (string_ptr, format, arg);
        va_end (arg);

        return rv;
}

/*
 *
 *
 */
void
__gf_free (void *free_ptr)
{
        size_t          req_size = 0;
        char            *ptr = NULL;
        uint32_t        type = 0;
        xlator_t        *xl = NULL;

        if (!THIS->ctx->mem_acct_enable) {
                FREE (free_ptr);
                return;
        }

        if (!free_ptr)
                return;

        ptr = (char *)free_ptr - 8 - 4;  /* 指針退到內存頭魔術字處,用來判斷是否正確分配的內存 */

        //Possible corruption, assert here
        GF_ASSERT (GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr);

        *(uint32_t *)ptr = 0;           /* 指針置0什麼意思? */

        ptr = ptr - sizeof(xlator_t *); /* 指針地址可以爲負 ? */
        memcpy (&xl, ptr, sizeof(xlator_t *));  /* 可以向NULL內存拷貝內容 ???*/

        //gf_free expects xl to be available
        GF_ASSERT (xl != NULL);

        if (!xl->mem_acct.rec) {
                ptr = (char *)free_ptr - GF_MEM_HEADER_SIZE;
                goto free;
        }


        ptr = ptr - sizeof(size_t);
        memcpy (&req_size, ptr, sizeof (size_t));
        ptr = ptr - 4;
        type = *(uint32_t *)ptr;

        // This points to a memory overrun
        GF_ASSERT (GF_MEM_TRAILER_MAGIC ==
                *(uint32_t *)((char *)free_ptr + req_size));

        *(uint32_t *) ((char *)free_ptr + req_size) = 0;

        LOCK (&xl->mem_acct.rec[type].lock);
        {
                xl->mem_acct.rec[type].size -= req_size;
                xl->mem_acct.rec[type].num_allocs--;
        }
        UNLOCK (&xl->mem_acct.rec[type].lock);
free:
        FREE (ptr);
}


/*
 * 分配內存池,有count個塊.
 * 每個塊大小爲sizeof_type(可用大小) + GF_MEM_POOL_PAD_BOUNDARY(存放管理信息)
 * 內存塊掛在mem_pool->pool鏈表上,內存池掛在: THIS->ctx->mempool_list 上
 *
 * 內存池名字: THIS->name:name 
 */
struct mem_pool *
mem_pool_new_fn (unsigned long sizeof_type,
                 unsigned long count, char *name)
{
        struct mem_pool  *mem_pool = NULL;
        unsigned long     padded_sizeof_type = 0;
        void             *pool = NULL;
        int               i = 0;
        int               ret = 0;
        struct list_head *list = NULL;
        glusterfs_ctx_t  *ctx = NULL;

        if (!sizeof_type || !count) {
                gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }
        padded_sizeof_type = sizeof_type + GF_MEM_POOL_PAD_BOUNDARY;

        mem_pool = GF_CALLOC (sizeof (*mem_pool), 1, gf_common_mt_mem_pool);
        if (!mem_pool)
                return NULL;

        ret = gf_asprintf (&mem_pool->name, "%s:%s", THIS->name, name);
        if (ret < 0)
                return NULL;

        if (!mem_pool->name) {
                GF_FREE (mem_pool);
                return NULL;
        }

        LOCK_INIT (&mem_pool->lock);
        INIT_LIST_HEAD (&mem_pool->list);
        INIT_LIST_HEAD (&mem_pool->global_list);

        mem_pool->padded_sizeof_type = padded_sizeof_type;
        mem_pool->cold_count = count;
        mem_pool->real_sizeof_type = sizeof_type;

        pool = GF_CALLOC (count, padded_sizeof_type, gf_common_mt_long);
        if (!pool) {
                GF_FREE (mem_pool->name);
                GF_FREE (mem_pool);
                return NULL;
        }

        for (i = 0; i < count; i++) {
                list = pool + (i * (padded_sizeof_type));
                INIT_LIST_HEAD (list);
                list_add_tail (list, &mem_pool->list);
        }

        mem_pool->pool = pool;
        mem_pool->pool_end = pool + (count * (padded_sizeof_type));

        /* add this pool to the global list */
        ctx = THIS->ctx;
        if (!ctx)
                goto out;

        list_add (&mem_pool->global_list, &ctx->mempool_list);

out:
        return mem_pool;
}

void*
mem_get0 (struct mem_pool *mem_pool)
{
        void     *ptr = NULL;

        if (!mem_pool) {
                gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }

        ptr = mem_get(mem_pool);

        if (ptr)
                memset(ptr, 0, mem_pool->real_sizeof_type);

        return ptr;
}

/*
 * 從內存池獲取一個內存塊
 * 
 * 如果內存池內存塊用完,則從系統內存分配一塊,並把該內存塊歸屬在該mem_pool,但不加入鏈表
 *
 */
void *
mem_get (struct mem_pool *mem_pool)
{
        struct list_head *list = NULL;
        void             *ptr = NULL;
        int             *in_use = NULL;
        struct mem_pool **pool_ptr = NULL;

        if (!mem_pool) {
                gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }

        LOCK (&mem_pool->lock);
        {
                mem_pool->alloc_count++;
                if (mem_pool->cold_count) {
                        list = mem_pool->list.next;
                        list_del (list);

                        mem_pool->hot_count++;
                        mem_pool->cold_count--;

                        if (mem_pool->max_alloc < mem_pool->hot_count)
                                mem_pool->max_alloc = mem_pool->hot_count;

                        ptr = list;
                        in_use = (ptr + GF_MEM_POOL_LIST_BOUNDARY +
                                  GF_MEM_POOL_PTR);
                        *in_use = 1;            // 設置內存塊被使用狀態

                        goto fwd_addr_out;
                }

                /* This is a problem area. If we've run out of
                 * chunks in our slab above, we need to allocate
                 * enough memory to service this request.
                 * The problem is, these individual chunks will fail
                 * the first address range check in __is_member. Now, since
                 * we're not allocating a full second slab, we wont have
                 * enough info perform the range check in __is_member.
                 *
                 * I am working around this by performing a regular allocation
                 * , just the way the caller would've done when not using the
                 * mem-pool. That also means, we're not padding the size with
                 * the list_head structure because, this will not be added to
                 * the list of chunks that belong to the mem-pool allocated
                 * initially.
                 *
                 * This is the best we can do without adding functionality for
                 * managing multiple slabs. That does not interest us at present
                 * because it is too much work knowing that a better slab
                 * allocator is coming RSN.
                 */

            /* 未從內存池申請到內存塊,則重新從系統申請內存
             * 該內存歸屬到mem_pool中,但未加入 mem_pool 的 list 鏈表中
             */
            {
                mem_pool->pool_misses++;
                mem_pool->curr_stdalloc++;
                if (mem_pool->max_stdalloc < mem_pool->curr_stdalloc)
                        mem_pool->max_stdalloc = mem_pool->curr_stdalloc;
                ptr = GF_CALLOC (1, mem_pool->padded_sizeof_type,
                                 gf_common_mt_mem_pool);
                gf_log_callingfn ("mem-pool", GF_LOG_DEBUG, "Mem pool is full. "
                                  "Callocing mem");
            }
                /* Memory coming from the heap need not be transformed from a
                 * chunkhead to a usable pointer since it is not coming from
                 * the pool.
                 */
        }
fwd_addr_out:
        pool_ptr = mem_pool_from_ptr (ptr);
        *pool_ptr = (struct mem_pool *)mem_pool;
        ptr = mem_pool_chunkhead2ptr (ptr);
        UNLOCK (&mem_pool->lock);

        return ptr;
}


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;
}

/*
 * 釋放一個內存塊
 * 
 * 若該內存塊是從mem_pool 中取得,則放回到mem_pool的list中。
 * 如果是從系統內存分配,則直接釋放,並把 mem_pool->curr_stdalloc 計數減一
 */
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_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
                return;
        }

        list = head = mem_pool_ptr2chunkhead (ptr);
        tmp = mem_pool_from_ptr (head);
        if (!tmp) {
                gf_log_callingfn ("mem-pool", GF_LOG_ERROR,
                                  "ptr header is corrupted");
                return;
        }

        pool = *tmp;
        if (!pool) {
                gf_log_callingfn ("mem-pool", GF_LOG_ERROR,
                                  "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_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.
                         */
                        pool->curr_stdalloc--;
                        GF_FREE (list);
                        break;
                default:
                        /* log error */
                        break;
                }
        }
        UNLOCK (&pool->lock);
}

/*
 * 註銷內存池
 *
 * 如果 pool->curr_stdalloc 不爲0,則存在內存泄漏 !!!
 */
void
mem_pool_destroy (struct mem_pool *pool)
{
        if (!pool)
                return;

        gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64,
                pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count);

        list_del (&pool->global_list);

        LOCK_DESTROY (&pool->lock);
        GF_FREE (pool->name);
        GF_FREE (pool->pool);
        GF_FREE (pool);

        return;
}


發佈了63 篇原創文章 · 獲贊 6 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章