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>