Annotation of libelwix/src/mem.c, revision 1.1
1.1 ! misho 1: /*************************************************************************
! 2: * (C) 2012 AITNET ltd - Sofia/Bulgaria - <misho@elwix.org>
! 3: * by Michael Pounov <misho@openbsd-bg.org>
! 4: *
! 5: * $Author: misho $
! 6: * $Id: mem.c,v 1.3 2012/07/25 15:21:59 misho Exp $
! 7: *
! 8: **************************************************************************
! 9: The ELWIX and AITNET software is distributed under the following
! 10: terms:
! 11:
! 12: All of the documentation and software included in the ELWIX and AITNET
! 13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
! 14:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
! 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
! 17:
! 18: Redistribution and use in source and binary forms, with or without
! 19: modification, are permitted provided that the following conditions
! 20: are met:
! 21: 1. Redistributions of source code must retain the above copyright
! 22: notice, this list of conditions and the following disclaimer.
! 23: 2. Redistributions in binary form must reproduce the above copyright
! 24: notice, this list of conditions and the following disclaimer in the
! 25: documentation and/or other materials provided with the distribution.
! 26: 3. All advertising materials mentioning features or use of this software
! 27: must display the following acknowledgement:
! 28: This product includes software developed by Michael Pounov <misho@elwix.org>
! 29: ELWIX - Embedded LightWeight unIX and its contributors.
! 30: 4. Neither the name of AITNET nor the names of its contributors
! 31: may be used to endorse or promote products derived from this software
! 32: without specific prior written permission.
! 33:
! 34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
! 35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 44: SUCH DAMAGE.
! 45: */
! 46: #include "global.h"
! 47:
! 48:
! 49: mpool_t *elwix_mpool;
! 50:
! 51:
! 52: /*
! 53: * mpool_init() - Init memory pool
! 54: *
! 55: * @maxmem = If !=0 set maximum memory quota
! 56: * return: =NULL error or !=NULL new allocated pool
! 57: */
! 58: mpool_t *
! 59: mpool_init(u_long maxmem)
! 60: {
! 61: mpool_t *mp;
! 62: register int i;
! 63:
! 64: mp = malloc(sizeof(mpool_t));
! 65: if (!mp) {
! 66: LOGERR;
! 67: return NULL;
! 68: } else
! 69: memset(mp, 0, sizeof(mpool_t));
! 70:
! 71: pthread_mutex_init(&mp->pool_mtx, NULL);
! 72:
! 73: mp->pool_quota.max = maxmem;
! 74:
! 75: mpool_lock(mp);
! 76: for (i = 0; i < MEM_BUCKETS; i++) {
! 77: TAILQ_INIT(&mp->pool_active[i]);
! 78: TAILQ_INIT(&mp->pool_inactive[i]);
! 79: }
! 80: mpool_unlock(mp);
! 81:
! 82: return mp;
! 83: }
! 84:
! 85: /*
! 86: * mpool_destroy() - Destroy memory pool
! 87: *
! 88: * @mp = Memory pool
! 89: * return: none
! 90: */
! 91: void
! 92: mpool_destroy(mpool_t ** __restrict mp)
! 93: {
! 94: struct tagAlloc *m;
! 95: register int i;
! 96:
! 97: if (!mp && !*mp)
! 98: return;
! 99:
! 100: mpool_lock(*mp);
! 101:
! 102: for (i = 0; i < MEM_BUCKETS; i++) {
! 103: while ((m = TAILQ_FIRST(&(*mp)->pool_active[i]))) {
! 104: TAILQ_REMOVE(&(*mp)->pool_active[i], m, alloc_node);
! 105: if (m->alloc_mem)
! 106: free(m->alloc_mem);
! 107: free(m);
! 108: }
! 109: while ((m = TAILQ_FIRST(&(*mp)->pool_inactive[i]))) {
! 110: TAILQ_REMOVE(&(*mp)->pool_inactive[i], m, alloc_node);
! 111: if (m->alloc_mem)
! 112: free(m->alloc_mem);
! 113: free(m);
! 114: }
! 115: }
! 116:
! 117: mpool_unlock(*mp);
! 118: pthread_mutex_destroy(&(*mp)->pool_mtx);
! 119:
! 120: free(*mp);
! 121: *mp = NULL;
! 122: }
! 123:
! 124: /* ----------------------------------------------------------- */
! 125:
! 126: static inline long
! 127: BucketIndex(u_int size)
! 128: {
! 129: register long b;
! 130:
! 131: if (!size--)
! 132: return 0; /* min bucket position in array */
! 133:
! 134: for (b = MEM_MIN_BUCKET; b < MEM_MAX_BUCKET; b++)
! 135: if (!(size >> b))
! 136: break;
! 137:
! 138: return b - MEM_MIN_BUCKET; /* convert to bucket array index */
! 139: }
! 140:
! 141: static inline struct tagAlloc *
! 142: pullInactive(mpool_t * __restrict mp, int idx)
! 143: {
! 144: struct tagAlloc *m = NULL;
! 145:
! 146: /* must be locked pool before use this function */
! 147: if ((m = TAILQ_FIRST(&mp->pool_inactive[idx]))) {
! 148: TAILQ_REMOVE(&mp->pool_inactive[idx], m, alloc_node);
! 149: /* statistics */
! 150: mp->pool_calls.cache--;
! 151: mp->pool_bytes.cache -= mem_size(m);
! 152:
! 153: /* clear name */
! 154: *m->alloc_name = 0;
! 155: }
! 156:
! 157: return m;
! 158: }
! 159:
! 160: /*
! 161: * mpool_malloc() - Memory allocation
! 162: *
! 163: * @mp = Memory pool
! 164: * @size = Size
! 165: * @memname = Optional memory block name
! 166: * return: NULL error or !=NULL ok allocated memory
! 167: */
! 168: void *
! 169: mpool_malloc(mpool_t * __restrict mp, u_int size, const char *memname)
! 170: {
! 171: struct tagAlloc *m;
! 172: int idx;
! 173: u_int align;
! 174:
! 175: if (!mp) {
! 176: elwix_SetErr(EINVAL, "Pool not specified");
! 177: return NULL;
! 178: }
! 179: if (size > MEM_ALLOC_MAX) {
! 180: elwix_SetErr(ENOMEM, "Memory size is too large");
! 181: return NULL;
! 182: } else
! 183: size = (size + 3) & ~3; /* must align to 4 because needed room for sentinels */
! 184:
! 185: idx = BucketIndex(size);
! 186:
! 187: mpool_lock(mp);
! 188:
! 189: /* get memory from cache if exists */
! 190: if (!(m = pullInactive(mp, idx))) {
! 191: /* quota */
! 192: if (mp->pool_quota.max &&
! 193: (mp->pool_quota.curr + size) > mp->pool_quota.max) {
! 194: elwix_SetErr(ENOMEM, "Max.allocate memory quota has been reached");
! 195: mpool_unlock(mp);
! 196: return NULL;
! 197: }
! 198:
! 199: m = malloc(sizeof(struct tagAlloc));
! 200: if (!m) {
! 201: LOGERR;
! 202: mpool_unlock(mp);
! 203: return NULL;
! 204: } else
! 205: memset(m, 0, sizeof(struct tagAlloc));
! 206: }
! 207:
! 208: if (memname)
! 209: strlcpy(m->alloc_name, memname, sizeof m->alloc_name);
! 210:
! 211: if (!m->alloc_mem) {
! 212: align = 1 << (idx + MEM_MIN_BUCKET);
! 213: m->alloc_mem = malloc(align + 12); /* +12 sentinel bytes */
! 214: if (!m->alloc_mem) {
! 215: LOGERR;
! 216: free(m);
! 217: mpool_unlock(mp);
! 218: return NULL;
! 219: } else { /* quota */
! 220: mp->pool_quota.curr += size;
! 221: memset(m->alloc_mem, 0, align + 12);
! 222: }
! 223: }
! 224:
! 225: m->alloc_mem[0] = size / sizeof(u_int);
! 226: m->alloc_mem[1] = MEM_MAGIC_START;
! 227: m->alloc_mem[2 + size / sizeof(u_int)] = MEM_MAGIC_STOP;
! 228: TAILQ_INSERT_HEAD(&mp->pool_active[idx], m, alloc_node);
! 229: /* statistics */
! 230: mp->pool_calls.alloc++;
! 231: mp->pool_bytes.alloc += size;
! 232:
! 233: mpool_unlock(mp);
! 234: return mem_data(m, void*);
! 235: }
! 236:
! 237: /*
! 238: * mpool_realloc() Reallocate memory block with new size
! 239: *
! 240: * @mp = Memory pool
! 241: * @data = Allocated memory data
! 242: * @newsize = New size of memory block
! 243: * @memname = Optional new memory block name
! 244: * return: NULL error or !=NULL new reallocated memory block
! 245: */
! 246: void *
! 247: mpool_realloc(mpool_t * __restrict mp, void * __restrict data, u_int newsize, const char *memname)
! 248: {
! 249: struct tagAlloc *m, *tmp;
! 250: int idx, oidx;
! 251: void *p;
! 252: u_int align, osize;
! 253:
! 254: /* if !data execute mpool_malloc() */
! 255: if (!data)
! 256: return mpool_malloc(mp, newsize, memname);
! 257:
! 258: if (!mp) {
! 259: elwix_SetErr(EINVAL, "Pool not specified");
! 260: return NULL;
! 261: }
! 262: /* check address range & sentinel */
! 263: if (MEM_BADADDR(data) || MEM_CORRUPT(data)) {
! 264: elwix_SetErr(EFAULT, "Corrupted memory address");
! 265: return NULL;
! 266: } else {
! 267: osize = ((u_int*)data)[-2] * sizeof(u_int);
! 268: oidx = BucketIndex(osize);
! 269: }
! 270: /* prepare new size */
! 271: if (newsize > MEM_ALLOC_MAX) {
! 272: elwix_SetErr(ENOMEM, "Memory size is too large");
! 273: return NULL;
! 274: } else {
! 275: newsize = (newsize + 3) & ~3; /* must align to 4 because needed room for sentinels */
! 276: idx = BucketIndex(newsize);
! 277: }
! 278:
! 279: mpool_lock(mp);
! 280:
! 281: /* quota */
! 282: if (mp->pool_quota.max &&
! 283: (mp->pool_quota.curr + ((u_long) newsize - osize)) > mp->pool_quota.max) {
! 284: elwix_SetErr(ENOMEM, "Max.allocate memory quota has been reached");
! 285: mpool_unlock(mp);
! 286: return NULL;
! 287: }
! 288:
! 289: /* find old memory block */
! 290: TAILQ_FOREACH_SAFE(m, &mp->pool_active[oidx], alloc_node, tmp) {
! 291: if (mem_data(m, void*) == data && mem_size(m) == osize) {
! 292: /* case in different buckets */
! 293: if (oidx != idx) {
! 294: TAILQ_REMOVE(&mp->pool_active[oidx], m, alloc_node);
! 295: /* statistics */
! 296: mp->pool_calls.alloc--;
! 297: }
! 298: mp->pool_bytes.alloc -= osize;
! 299: break;
! 300: }
! 301: }
! 302: /* memory block not found! */
! 303: if (!m) {
! 304: mpool_unlock(mp);
! 305: elwix_SetErr(EFAULT, "Memory block not found");
! 306: return NULL;
! 307: }
! 308:
! 309: /* try to reallocate memory block to new bucket */
! 310: if (oidx != idx) {
! 311: align = 1 << (idx + MEM_MIN_BUCKET);
! 312: p = realloc(m->alloc_mem, align + 12);
! 313: if (!p) {
! 314: LOGERR;
! 315:
! 316: /* restore to old bucket pulled memory block for reallocation */
! 317: TAILQ_INSERT_HEAD(&mp->pool_active[oidx], m, alloc_node);
! 318: /* statistics */
! 319: mp->pool_calls.alloc++;
! 320: mp->pool_bytes.alloc += osize;
! 321:
! 322: mpool_unlock(mp);
! 323: return NULL;
! 324: } else
! 325: m->alloc_mem = (u_int*) p;
! 326: }
! 327: /* quota */
! 328: mp->pool_quota.curr += (u_long) newsize - osize;
! 329:
! 330: m->alloc_mem[0] = newsize / sizeof(u_int);
! 331: m->alloc_mem[1] = MEM_MAGIC_START;
! 332: m->alloc_mem[2 + newsize / sizeof(u_int)] = MEM_MAGIC_STOP;
! 333:
! 334: if (oidx != idx) {
! 335: TAILQ_INSERT_HEAD(&mp->pool_active[idx], m, alloc_node);
! 336: /* statistics */
! 337: mp->pool_calls.alloc++;
! 338: }
! 339: mp->pool_bytes.alloc += newsize;
! 340:
! 341: if (memname)
! 342: strlcpy(m->alloc_name, memname, sizeof m->alloc_name);
! 343:
! 344: mpool_unlock(mp);
! 345: return mem_data(m, void*);
! 346: }
! 347:
! 348: /*
! 349: * mpool_purge() - Purge memory block cache and release resources
! 350: *
! 351: * @mp = Memory pool
! 352: * @atmost = Free at most in buckets
! 353: * return: -1 error or 0 ok
! 354: */
! 355: int
! 356: mpool_purge(mpool_t * __restrict mp, u_int atmost)
! 357: {
! 358: register int i, cx;
! 359: struct tagAlloc *m, *tmp;
! 360:
! 361: if (!mp) {
! 362: elwix_SetErr(EINVAL, "Pool not specified");
! 363: return -1;
! 364: }
! 365:
! 366: mpool_lock(mp);
! 367:
! 368: for (i = cx = 0; i < MEM_BUCKETS; cx = 0, i++) {
! 369: TAILQ_FOREACH_SAFE(m, &mp->pool_inactive[i], alloc_node, tmp) {
! 370: /* barrier for purge */
! 371: if (cx < atmost) {
! 372: cx++;
! 373: continue;
! 374: }
! 375:
! 376: TAILQ_REMOVE(&mp->pool_inactive[i], m, alloc_node);
! 377: /* statistics */
! 378: mp->pool_calls.cache--;
! 379: mp->pool_bytes.cache -= mem_size(m);
! 380:
! 381: mp->pool_calls.free++;
! 382: mp->pool_bytes.free += mem_size(m);
! 383: /* quota */
! 384: mp->pool_quota.curr -= mem_size(m);
! 385:
! 386: if (m->alloc_mem)
! 387: free(m->alloc_mem);
! 388: free(m);
! 389: }
! 390: }
! 391:
! 392: mpool_unlock(mp);
! 393: return 0;
! 394: }
! 395:
! 396: /*
! 397: * mpool_free() Free allocated memory with mpool_alloc()
! 398: *
! 399: * @mp = Memory pool
! 400: * @data = Allocated memory data
! 401: * @purge = if !=0 force release memory block
! 402: * return: <0 error or 0 ok released memory block
! 403: */
! 404: int
! 405: mpool_free(mpool_t * __restrict mp, void * __restrict data, int purge)
! 406: {
! 407: int idx;
! 408: struct tagAlloc *m, *tmp;
! 409:
! 410: assert(data);
! 411: if (!mp) {
! 412: elwix_SetErr(EINVAL, "Pool not specified");
! 413: return -1;
! 414: }
! 415: /* check address range & sentinel */
! 416: assert(!MEM_BADADDR(data) && !MEM_CORRUPT(data));
! 417: if (MEM_BADADDR(data) || MEM_CORRUPT(data)) {
! 418: elwix_SetErr(EFAULT, "Corrupted memory address");
! 419: return -2;
! 420: } else
! 421: idx = BucketIndex(((u_int*)data)[-2] * sizeof(u_int));
! 422:
! 423: mpool_lock(mp);
! 424: TAILQ_FOREACH_SAFE(m, &mp->pool_active[idx], alloc_node, tmp)
! 425: if (mem_data(m, void*) == data) {
! 426: TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node);
! 427: /* statistics */
! 428: mp->pool_calls.alloc--;
! 429: mp->pool_bytes.alloc -= mem_size(m);
! 430:
! 431: if (!purge) {
! 432: TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node);
! 433: /* statistics */
! 434: mp->pool_calls.cache++;
! 435: mp->pool_bytes.cache += mem_size(m);
! 436: } else {
! 437: /* statistics */
! 438: mp->pool_calls.free++;
! 439: mp->pool_bytes.free += mem_size(m);
! 440: /* quota */
! 441: mp->pool_quota.curr -= mem_size(m);
! 442:
! 443: if (m->alloc_mem)
! 444: free(m->alloc_mem);
! 445: free(m);
! 446: }
! 447: break;
! 448: }
! 449: mpool_unlock(mp);
! 450:
! 451: return 0;
! 452: }
! 453:
! 454: /*
! 455: * mpool_free2() Free allocated memory with mpool_alloc() by size and memory name
! 456: *
! 457: * @mp = Memory pool
! 458: * @size = Allocated memory data size
! 459: * @memname = Memory name
! 460: * @purge = if !=0 force release memory block
! 461: * return: <0 error or 0 ok released memory block
! 462: */
! 463: int
! 464: mpool_free2(mpool_t * __restrict mp, u_int size, const char *memname, int purge)
! 465: {
! 466: int idx;
! 467: struct tagAlloc *m, *tmp;
! 468:
! 469: if (!mp || !memname) {
! 470: elwix_SetErr(EINVAL, "Pool or memory name is not specified");
! 471: return -1;
! 472: } else
! 473: idx = BucketIndex(size);
! 474:
! 475: mpool_lock(mp);
! 476: TAILQ_FOREACH_SAFE(m, &mp->pool_active[idx], alloc_node, tmp)
! 477: if (!strcmp(m->alloc_name, memname)) {
! 478: TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node);
! 479: /* statistics */
! 480: mp->pool_calls.alloc--;
! 481: mp->pool_bytes.alloc -= mem_size(m);
! 482:
! 483: if (!purge) {
! 484: TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node);
! 485: /* statistics */
! 486: mp->pool_calls.cache++;
! 487: mp->pool_bytes.cache += mem_size(m);
! 488: } else {
! 489: /* statistics */
! 490: mp->pool_calls.free++;
! 491: mp->pool_bytes.free += mem_size(m);
! 492: /* quota */
! 493: mp->pool_quota.curr -= mem_size(m);
! 494:
! 495: if (m->alloc_mem)
! 496: free(m->alloc_mem);
! 497: free(m);
! 498: }
! 499: break;
! 500: }
! 501: mpool_unlock(mp);
! 502:
! 503: return 0;
! 504: }
! 505:
! 506: /*
! 507: * mpool_strdup() - String duplicate
! 508: *
! 509: * @mp = Memory pool
! 510: * @str = String
! 511: * @memname = Memory name
! 512: * return: NULL error or !=NULL new string
! 513: */
! 514: char *
! 515: mpool_strdup(mpool_t * __restrict mp, const char *str, const char *memname)
! 516: {
! 517: char *s = NULL;
! 518: u_int len;
! 519:
! 520: if (!mp) {
! 521: elwix_SetErr(EINVAL, "Pool not specified");
! 522: return NULL;
! 523: }
! 524: if (!str) {
! 525: elwix_SetErr(EINVAL, "String is NULL");
! 526: return NULL;
! 527: } else
! 528: len = strlen(str) + 1;
! 529:
! 530: s = mpool_malloc(mp, len, memname);
! 531: if (!s)
! 532: return NULL;
! 533: else
! 534: memcpy(s, str, len);
! 535:
! 536: return s;
! 537: }
! 538:
! 539: /*
! 540: * mpool_getmembynam() Find allocated memory block by size and memory name
! 541: *
! 542: * @mp = Memory pool
! 543: * @size = Memory size
! 544: * @memname = Memory name
! 545: * return: NULL error or not found and !=NULL allocated memory
! 546: */
! 547: inline struct tagAlloc *
! 548: mpool_getmembynam(mpool_t * __restrict mp, u_int size, const char *memname)
! 549: {
! 550: int idx;
! 551: struct tagAlloc *m = NULL;
! 552:
! 553: if (!mp || !memname)
! 554: return NULL;
! 555:
! 556: idx = BucketIndex(size);
! 557: TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node)
! 558: if (!strcmp(m->alloc_name, memname))
! 559: break;
! 560:
! 561: return mem_data(m, void*);
! 562: }
! 563:
! 564: /*
! 565: * mpool_getsizebyaddr() - Get size of allocated memory block by address
! 566: *
! 567: * @addr = allocated memory from mpool_malloc()
! 568: * return: usable size of allocated memory block
! 569: */
! 570: inline u_int
! 571: mpool_getsizebyaddr(void * __restrict data)
! 572: {
! 573: if (mpool_chkaddr(data))
! 574: return 0;
! 575:
! 576: return (((u_int*) data)[-2] * sizeof(u_int));
! 577: }
! 578:
! 579: /*
! 580: * mpool_chkaddr() - Check validity of given address
! 581: *
! 582: * @data = allocated memory from mpool_malloc()
! 583: * return: -1 bad address, 1 corrupted address or 0 ok
! 584: */
! 585: inline int
! 586: mpool_chkaddr(void * __restrict data)
! 587: {
! 588: /* check address range */
! 589: if (MEM_BADADDR(data))
! 590: return -1;
! 591: /* check sentinel */
! 592: if (MEM_CORRUPT(data))
! 593: return 1;
! 594: /* data address is ok! */
! 595: return 0;
! 596: }
! 597:
! 598: /*
! 599: * mpool_setquota() - Change maximum memory quota
! 600: *
! 601: * @mp = Memory pool
! 602: * @maxmem = New max quota size
! 603: * return: old maximum memory quota size
! 604: */
! 605: inline u_long
! 606: mpool_setquota(mpool_t * __restrict mp, u_long maxmem)
! 607: {
! 608: u_long ret;
! 609:
! 610: if (!mp)
! 611: return 0;
! 612:
! 613: ret = mp->pool_quota.max;
! 614: mp->pool_quota.max = maxmem;
! 615:
! 616: /* if new max quota is less then current allocated memory,
! 617: * try to purge memory cache blocks
! 618: */
! 619: if (mp->pool_quota.max < mp->pool_quota.curr)
! 620: mpool_purge(mp, 0);
! 621:
! 622: return ret;
! 623: }
! 624:
! 625: /*
! 626: * mpool_getquota() - Get memory quota
! 627: *
! 628: * @mp = Memory pool
! 629: * @currmem = Return current memory
! 630: * @maxmem = Return max quota size
! 631: * return: none
! 632: */
! 633: inline void
! 634: mpool_getquota(mpool_t * __restrict mp, u_long *currmem, u_long *maxmem)
! 635: {
! 636: if (!mp)
! 637: return;
! 638:
! 639: if (maxmem)
! 640: *maxmem = mp->pool_quota.max;
! 641: if (currmem)
! 642: *currmem = mp->pool_quota.curr;
! 643: }
! 644:
! 645: /* ----------------------------------------------------------- */
! 646:
! 647: /*
! 648: * mpool_statistics() - Dump statistics from memory pool buckets
! 649: *
! 650: * @mp = Memory pool
! 651: * @cb = Export statistics to callback
! 652: * return: none
! 653: */
! 654: void
! 655: mpool_statistics(mpool_t * __restrict mp, mpool_stat_cb cb)
! 656: {
! 657: struct tagAlloc *m;
! 658: register int i, act, inact;
! 659:
! 660: if (!mp || !cb)
! 661: return;
! 662:
! 663: for (i = act = inact = 0; i < MEM_BUCKETS; act = inact = 0, i++) {
! 664: TAILQ_FOREACH(m, &mp->pool_active[i], alloc_node)
! 665: act++;
! 666: TAILQ_FOREACH(m, &mp->pool_inactive[i], alloc_node)
! 667: inact++;
! 668:
! 669: cb(1 << (i + MEM_MIN_BUCKET), act, inact);
! 670: }
! 671: }
! 672:
! 673: /* ----------------------------------------------------------- */
! 674:
! 675: /*
! 676: * mpool_xmalloc() - malloc wrapper
! 677: *
! 678: * @size = Size
! 679: * return: NULL error or !=NULL ok allocated memory
! 680: */
! 681: void *
! 682: mpool_xmalloc(size_t size)
! 683: {
! 684: return mpool_malloc(elwix_mpool, size, elwix_Prog);
! 685: }
! 686:
! 687: /*
! 688: * mpool_xcalloc() - calloc wrapper
! 689: *
! 690: * @num = number of elements
! 691: * @size = Size of element
! 692: * return: NULL error or !=NULL ok allocated memory
! 693: */
! 694: void *
! 695: mpool_xcalloc(size_t num, size_t size)
! 696: {
! 697: return mpool_malloc(elwix_mpool, num * size, elwix_Prog);
! 698: }
! 699:
! 700: /*
! 701: * mpool_xrealloc() - realloc wrapper
! 702: *
! 703: * @data = Allocated memory data
! 704: * @newsize = New size of memory block
! 705: * return: NULL error or !=NULL new reallocated memory block
! 706: */
! 707: void *
! 708: mpool_xrealloc(void * __restrict data, size_t newsize)
! 709: {
! 710: return mpool_realloc(elwix_mpool, data, newsize, elwix_Prog);
! 711: }
! 712:
! 713: /*
! 714: * mpool_xfree() - free wrapper
! 715: *
! 716: * @data = Allocated memory data
! 717: * return: none
! 718: */
! 719: void
! 720: mpool_xfree(void * __restrict data)
! 721: {
! 722: mpool_free(elwix_mpool, data, 0);
! 723: }
! 724:
! 725: /*
! 726: * mpool_xstrdup() - strdup wrapper
! 727: *
! 728: * @str = string
! 729: * return: =NULL error or !=NULL new allocated string
! 730: */
! 731: char *
! 732: mpool_xstrdup(const char *str)
! 733: {
! 734: return mpool_strdup(elwix_mpool, str, elwix_Prog);
! 735: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>