cb63a575751c4a60e48340bd320934cccb053f75 braney Wed May 29 13:14:08 2019 -0700 some tweaks to the lm allocater to allow it to use a memory block passed into rather than allocating its own memory. Also a checkpoint routine for the memory allocators that allows a caller to find out how much memory has been allocated since the last time it was called. diff --git src/lib/memalloc.c src/lib/memalloc.c index 89aa3ff..128824c 100644 --- src/lib/memalloc.c +++ src/lib/memalloc.c @@ -3,30 +3,42 @@ * memory handler is a thin shell around malloc/free. You can * substitute routines that do more integrety checking with * pushCarefulMem(), or routines of your own devising with * pushMemHandler(). * * This file is copyright 2002 Jim Kent, but license is hereby * granted for all use - public, private or commercial. */ #include #include "common.h" #include "obscure.h" #include "memalloc.h" #include "dlist.h" +static unsigned long memAlloced; + +unsigned long memCheckPoint() +/* Return the amount of memory allocated since last called. */ +{ +unsigned long ret = memAlloced; + +memAlloced = 0; + +return ret; +} + static void *defaultAlloc(size_t size) /* Default allocator. */ { return malloc(size); } static void defaultFree(void *vpt) /* Default deallocator. */ { free(vpt); } static void *defaultRealloc(void *vpt, size_t size) /* Default deallocator. */ { @@ -80,30 +92,31 @@ { maxAlloc = s; } void *needLargeMem(size_t size) /* This calls abort if the memory allocation fails. The memory is * not initialized to zero. */ { void *pt; if (size == 0 || size >= maxAlloc) errAbort("needLargeMem: trying to allocate %llu bytes (limit: %llu)", (unsigned long long)size, (unsigned long long)maxAlloc); if ((pt = mhStack->alloc(size)) == NULL) errAbort("needLargeMem: Out of memory - request size %llu bytes, errno: %d\n", (unsigned long long)size, errno); +memAlloced += size; return pt; } void *needLargeZeroedMem(size_t size) /* Request a large block of memory and zero it. */ { void *v; v = needLargeMem(size); memset(v, 0, size); return v; } void *needLargeMemResize(void* vp, size_t size) /* Adjust memory size on a block, possibly relocating it. If vp is NULL, * a new memory block is allocated. Memory not initted. */ @@ -125,30 +138,31 @@ void *v = needLargeMemResize(vp, newSize); if (newSize > oldSize) memset(((char*)v)+oldSize, 0, newSize-oldSize); return v; } void *needHugeMem(size_t size) /* No checking on size. Memory not initted. */ { void *pt; if (size == 0) errAbort("needHugeMem: trying to allocate 0 bytes"); if ((pt = mhStack->alloc(size)) == NULL) errAbort("needHugeMem: Out of huge memory - request size %llu bytes, errno: %d\n", (unsigned long long)size, errno); +memAlloced += size; return pt; } void *needHugeZeroedMem(size_t size) /* Request a large block of memory and zero it. */ { void *v; v = needHugeMem(size); memset(v, 0, size); return v; } void *needHugeMemResize(void* vp, size_t size) /* Adjust memory size on a block, possibly relocating it. If vp is NULL, @@ -177,45 +191,47 @@ #define NEEDMEM_LIMIT 500000000 void *needMem(size_t size) /* Need mem calls abort if the memory allocation fails. The memory * is initialized to zero. */ { void *pt; if (size == 0 || size > NEEDMEM_LIMIT) errAbort("needMem: trying to allocate %llu bytes (limit: %llu)", (unsigned long long)size, (unsigned long long)NEEDMEM_LIMIT); if ((pt = mhStack->alloc(size)) == NULL) errAbort("needMem: Out of memory - request size %llu bytes, errno: %d\n", (unsigned long long)size, errno); memset(pt, 0, size); +memAlloced += size; return pt; } void *needMoreMem(void *old, size_t oldSize, size_t newSize) /* Adjust memory size on a block, possibly relocating it. If vp is NULL, a * new memory block is allocated. No checking on size. If block is grown, * new memory is zeroed. */ { return needLargeZeroedMemResize(old, oldSize, newSize); } void *wantMem(size_t size) /* Want mem just calls malloc - no zeroing of memory, no * aborting if request fails. */ { +memAlloced += size; return mhStack->alloc(size); } void freeMem(void *pt) /* Free memory will check for null before freeing. */ { if (pt != NULL) mhStack->free(pt); } void freez(void *vpt) /* Pass address of pointer. Will free pointer and set it * to NULL. */ { void **ppt = (void **)vpt; @@ -293,30 +309,31 @@ sprintLongWithCommas(maxAlloc, (long long)carefulMaxToAlloc); sprintLongWithCommas(allocRequest, (long long)newAlloced); pthread_mutex_unlock( &carefulMutex ); // Avoid out-of-memory issues by exiting immediately. char errMsg[1024]; safef(errMsg, sizeof errMsg, "carefulAlloc: Allocated too much memory - more than %s bytes (%s). Exiting.\n", maxAlloc, allocRequest); write(STDERR_FILENO, errMsg, strlen(errMsg)); exit(1); // out of memory is a serious problem, exit immediately, but allow atexit cleanup. // avoid errAbort which allocates memory causing problems. } carefulAlloced = newAlloced; aliSize = ((size + sizeof(*cmb) + 4 + carefulAlignAdd)&carefulAlignMask); cmb = carefulParent->alloc(aliSize); +memAlloced += size; cmb->size = size; cmb->startCookie = cmbStartCookie; pEndCookie = (char *)(cmb+1); pEndCookie += size; memcpy(pEndCookie, cmbEndCookie, sizeof(cmbEndCookie)); dlAddHead(cmbAllocedList, (struct dlNode *)cmb); pthread_mutex_unlock( &carefulMutex ); return (void *)(cmb+1); } static void carefulFree(void *vpt) /* Check cookies and free. */ { pthread_mutex_lock( &carefulMutex ); struct carefulMemBlock *cmb = ((struct carefulMemBlock *)vpt)-1; @@ -446,30 +463,31 @@ struct dlList *list; /* List of allocated blocks. */ struct memHandler *parent; /* Underlying memory handler. */ struct memHandler *handler; /* Memory handler. */ }; static struct memTracker *memTracker = NULL; /* Head in memTracker list. */ static void *memTrackerAlloc(size_t size) /* Allocate extra memory for cookies and list node, and then * return memory block. */ { struct dlNode *node; size += sizeof (*node); node = memTracker->parent->alloc(size); +memAlloced += size; if (node == NULL) return node; dlAddTail(memTracker->list, node); return (void*)(node+1); } static void memTrackerFree(void *vpt) /* Check cookies and free. */ { struct dlNode *node = vpt; node -= 1; dlRemove(node); memTracker->parent->free(node); }