Annotation of libaitsess/src/mem.c, revision 1.1.2.1

1.1.2.1 ! misho       1: #include "global.h"
        !             2: 
        !             3: 
        !             4: /*
        !             5:  * mpool_init() - Init memory pool
        !             6:  *
        !             7:  * return: =NULL error or !=NULL new allocated pool
        !             8:  */
        !             9: mpool_t *
        !            10: mpool_init(void)
        !            11: {
        !            12:        mpool_t *mp;
        !            13: 
        !            14:        mp = malloc(sizeof(mpool_t));
        !            15:        if (!mp) {
        !            16:                LOGERR;
        !            17:                return NULL;
        !            18:        } else
        !            19:                memset(mp, 0, sizeof(mpool_t));
        !            20: 
        !            21:        pthread_mutex_init(&mp->pool_mtx, NULL);
        !            22:        return mp;
        !            23: }
        !            24: 
        !            25: /*
        !            26:  * mpool_destroy() - Destroy memory pool
        !            27:  *
        !            28:  * @mp = Memory pool
        !            29:  * return: none
        !            30:  */
        !            31: void
        !            32: mpool_destroy(mpool_t ** __restrict mp)
        !            33: {
        !            34:        struct tagAlloc *m;
        !            35:        register int i;
        !            36: 
        !            37:        if (!mp && !*mp)
        !            38:                return;
        !            39: 
        !            40:        mpool_lock(*mp);
        !            41: 
        !            42:        for (i = 0; i < MEM_BUCKETS; i++) {
        !            43:                while ((m = TAILQ_FIRST(&(*mp)->pool_active[i]))) {
        !            44:                        TAILQ_REMOVE(&(*mp)->pool_active[i], m, alloc_node);
        !            45:                        if (m->alloc_mem)
        !            46:                                free(m->alloc_mem);
        !            47:                        free(m);
        !            48:                }
        !            49:                while ((m = TAILQ_FIRST(&(*mp)->pool_inactive[i]))) {
        !            50:                        TAILQ_REMOVE(&(*mp)->pool_inactive[i], m, alloc_node);
        !            51:                        if (m->alloc_mem)
        !            52:                                free(m->alloc_mem);
        !            53:                        free(m);
        !            54:                }
        !            55:        }
        !            56: 
        !            57:        mpool_unlock(*mp);
        !            58:        pthread_mutex_destroy(&(*mp)->pool_mtx);
        !            59: 
        !            60:        free(*mp);
        !            61:        *mp = NULL;
        !            62: }
        !            63: 
        !            64: /* ----------------------------------------------------------- */
        !            65: 
        !            66: static inline long
        !            67: BucketIndex(u_int size)
        !            68: {
        !            69:        register long b;
        !            70: 
        !            71:        if (!size--)
        !            72:                return 0;               /* min bucket position in array */
        !            73: 
        !            74:        for (b = MEM_MIN_BUCKET; b < MEM_MAX_BUCKET; b++)
        !            75:                if (!(size >> b))
        !            76:                        break;
        !            77: 
        !            78:        return b - MEM_MIN_BUCKET;      /* convert to bucket array index */
        !            79: }
        !            80: 
        !            81: static inline struct tagAlloc *
        !            82: pullInactive(mpool_t * __restrict mp, int idx)
        !            83: {
        !            84:        struct tagAlloc *m = NULL;
        !            85: 
        !            86:        /* must be locked pool before use this function */ 
        !            87:        if ((m = TAILQ_FIRST(&mp->pool_inactive[idx]))) {
        !            88:                TAILQ_REMOVE(&mp->pool_inactive[idx], m, alloc_node);
        !            89: 
        !            90:                /* clear name */
        !            91:                *m->alloc_name = 0;
        !            92:                /* clear flags */
        !            93:                m->alloc_flags ^= m->alloc_flags;
        !            94:        }
        !            95: 
        !            96:        return m;
        !            97: }
        !            98: 
        !            99: /*
        !           100:  * mpool_malloc() - Memory allocation
        !           101:  *
        !           102:  * @mp = Memory pool
        !           103:  * @size = Size
        !           104:  * @memname = Optional memory block name
        !           105:  * return: NULL error or !=NULL ok allocated memory
        !           106:  */
        !           107: void *
        !           108: mpool_malloc(mpool_t * __restrict mp, u_int size, const char *memname)
        !           109: {
        !           110:        struct tagAlloc *m;
        !           111:        int idx, align;
        !           112: 
        !           113:        if (!mp) {
        !           114:                sess_SetErr(EINVAL, "Pool not specified");
        !           115:                return NULL;
        !           116:        }
        !           117:        if (size > MEM_ALLOC_MAX) {
        !           118:                sess_SetErr(ENOMEM, "Memory size is too large");
        !           119:                return NULL;
        !           120:        } else
        !           121:                size = (size + 3) & ~3; /* must align to 4 because needed room for sentinels */
        !           122: 
        !           123:        idx = BucketIndex(size);
        !           124: 
        !           125:        mpool_lock(mp);
        !           126: 
        !           127:        /* get memory from cache if exists */
        !           128:        if (!(m = pullInactive(mp, idx))) {
        !           129:                /* quota */
        !           130:                if (mp->pool_quota.max && 
        !           131:                                (mp->pool_quota.curr + size) > mp->pool_quota.max) {
        !           132:                        sess_SetErr(ENOMEM, "Max.allocate memory quota has been reached");
        !           133:                        mpool_unlock(mp);
        !           134:                        return NULL;
        !           135:                }
        !           136: 
        !           137:                m = malloc(sizeof(struct tagAlloc));
        !           138:                if (!m) {
        !           139:                        LOGERR;
        !           140:                        mpool_unlock(mp);
        !           141:                        return NULL;
        !           142:                } else
        !           143:                        memset(m, 0, sizeof(struct tagAlloc));
        !           144:        }
        !           145: 
        !           146:        if (memname)
        !           147:                strlcpy(m->alloc_name, memname, sizeof m->alloc_name);
        !           148: 
        !           149:        if (!m->alloc_mem) {
        !           150:                align = 1 << (idx + MEM_MIN_BUCKET);
        !           151:                m->alloc_mem = malloc(align + 12);      /* +12 sentinel bytes */
        !           152:                if (!m->alloc_mem) {
        !           153:                        LOGERR;
        !           154:                        free(m);
        !           155:                        mpool_unlock(mp);
        !           156:                        return NULL;
        !           157:                } else  /* quota */
        !           158:                        mp->pool_quota.curr += size;
        !           159:        }
        !           160: 
        !           161:        m->alloc_mem[0] = size / sizeof(u_int);
        !           162:        m->alloc_mem[1] = MEM_MAGIC_START;
        !           163:        m->alloc_mem[2 + size / sizeof(u_int)] = MEM_MAGIC_STOP;
        !           164:        TAILQ_INSERT_HEAD(&mp->pool_active[idx], m, alloc_node);
        !           165:        /* statistics */
        !           166:        mp->pool_calls.alloc++;
        !           167:        mp->pool_bytes.alloc += size;
        !           168: 
        !           169:        mpool_unlock(mp);
        !           170:        return mem_data(m, void*);
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * mpool_free() Free allocated memory with mpool_alloc()
        !           175:  *
        !           176:  * @mp = Memory pool
        !           177:  * @data = Allocated memory data
        !           178:  * @purge = if !=0 force release memory block
        !           179:  * return: <0 error or 0 ok released memory block
        !           180:  */
        !           181: int
        !           182: mpool_free(mpool_t * __restrict mp, void * __restrict data, int purge)
        !           183: {
        !           184:        int idx;
        !           185:        struct tagAlloc *m;
        !           186: 
        !           187:        if (!mp) {
        !           188:                sess_SetErr(EINVAL, "Pool not specified");
        !           189:                return -1;
        !           190:        }
        !           191:        /* check address range & sentinel */
        !           192:        if (MEM_BADADDR(data) || MEM_CORRUPT(data)) {
        !           193:                sess_SetErr(EFAULT, "Corrupted memory address");
        !           194:                return -2;
        !           195:        } else
        !           196:                idx = BucketIndex(((u_int*)data)[-2]);
        !           197: 
        !           198:        mpool_lock(mp);
        !           199:        TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node)
        !           200:                if (mem_data(m, void*) == data) {
        !           201:                        TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node);
        !           202: 
        !           203:                        if (!purge) {
        !           204:                                TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node);
        !           205:                                /* statistics */
        !           206:                                mp->pool_calls.cache++;
        !           207:                                mp->pool_bytes.cache += mem_size(m);
        !           208:                        } else {
        !           209:                                if (m->alloc_mem)
        !           210:                                        free(m->alloc_mem);
        !           211:                                free(m);
        !           212:                                /* statistics */
        !           213:                                mp->pool_calls.free++;
        !           214:                                mp->pool_bytes.free += mem_size(m);
        !           215:                        }
        !           216:                        break;
        !           217:                }
        !           218:        mpool_unlock(mp);
        !           219: 
        !           220:        return 0;
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * mpool_free2() Free allocated memory with mpool_alloc() by size and memory name
        !           225:  *
        !           226:  * @mp = Memory pool
        !           227:  * @size = Allocated memory data size
        !           228:  * @memname = Memory name
        !           229:  * @purge = if !=0 force release memory block
        !           230:  * return: <0 error or 0 ok released memory block
        !           231:  */
        !           232: int
        !           233: mpool_free2(mpool_t * __restrict mp, u_int size, const char *memname, int purge)
        !           234: {
        !           235:        int idx;
        !           236:        struct tagAlloc *m;
        !           237: 
        !           238:        if (!mp || !memname) {
        !           239:                sess_SetErr(EINVAL, "Pool or memory name is not specified");
        !           240:                return -1;
        !           241:        } else
        !           242:                idx = BucketIndex(size);
        !           243: 
        !           244:        mpool_lock(mp);
        !           245:        TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node)
        !           246:                if (!strcmp(m->alloc_name, memname)) {
        !           247:                        TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node);
        !           248: 
        !           249:                        if (!purge) {
        !           250:                                TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node);
        !           251:                                /* statistics */
        !           252:                                mp->pool_calls.cache++;
        !           253:                                mp->pool_bytes.cache += mem_size(m);
        !           254:                        } else {
        !           255:                                if (m->alloc_mem)
        !           256:                                        free(m->alloc_mem);
        !           257:                                free(m);
        !           258:                                /* statistics */
        !           259:                                mp->pool_calls.free++;
        !           260:                                mp->pool_bytes.free += mem_size(m);
        !           261:                        }
        !           262:                        break;
        !           263:                }
        !           264:        mpool_unlock(mp);
        !           265: 
        !           266:        return 0;
        !           267: }
        !           268: 
        !           269: /*
        !           270:  * mpool_getmembynam() Find allocated memory block by size and memory name
        !           271:  *
        !           272:  * @mp = Memory pool
        !           273:  * @size = Memory size
        !           274:  * @memname = Memory name
        !           275:  * return: NULL error or not found and !=NULL allocated memory 
        !           276:  */
        !           277: inline struct tagAlloc *
        !           278: mpool_getmembynam(mpool_t * __restrict mp, u_int size, const char *memname)
        !           279: {
        !           280:        int idx;
        !           281:        struct tagAlloc *m = NULL;
        !           282: 
        !           283:        if (!mp || !memname)
        !           284:                return NULL;
        !           285: 
        !           286:        idx = BucketIndex(size);
        !           287:        TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node)
        !           288:                if (!strcmp(m->alloc_name, memname))
        !           289:                        break;
        !           290: 
        !           291:        return mem_data(m, void*);
        !           292: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>