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 <pthread.h>
 #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);
 }