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/localmem.c src/lib/localmem.c
index 706ad15..8c5a33c 100644
--- src/lib/localmem.c
+++ src/lib/localmem.c
@@ -6,75 +6,102 @@
  *
  * This file is copyright 2002 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 
 #include "common.h"
 #include "localmem.h"
 
 
 struct lm
     {
     struct lmBlock *blocks;
     size_t blockSize;
     size_t allignMask;
     size_t allignAdd;
+    boolean doMemoryAllocs; // if true, do our own memory allocs, otherwise use passed in pointer
     };
 
 struct lmBlock
     {
     struct lmBlock *next;
     char *free;
     char *end;
     char *extra;
     };
 
 static struct lmBlock *newBlock(struct lm *lm, size_t reqSize)
 /* Allocate a new block of at least reqSize */
 {
 size_t size = (reqSize > lm->blockSize ? reqSize : lm->blockSize);
 size_t fullSize = size + sizeof(struct lmBlock);
 struct lmBlock *mb = needLargeZeroedMem(fullSize);
 if (mb == NULL)
     errAbort("Couldn't allocate %lld bytes", (long long)fullSize);
 mb->free = (char *)(mb+1);
 mb->end = ((char *)mb) + fullSize;
 mb->next = lm->blocks;
 lm->blocks = mb;
 return mb;
 }
 
-struct lm *lmInit(int blockSize)
+struct lm *lmGuts(int blockSize, void *mem)
 /* Create a local memory pool. */
 {
 struct lm *lm;
 int aliSize = sizeof(long);
 if (aliSize < sizeof(double))
     aliSize = sizeof(double);
 if (aliSize < sizeof(void *))
     aliSize = sizeof(void *);
 lm = needMem(sizeof(*lm));
 lm->blocks = NULL;
 if (blockSize <= 0)
     blockSize = (1<<14);    /* 16k default. */
 lm->blockSize = blockSize;
 lm->allignAdd = (aliSize-1);
 lm->allignMask = ~lm->allignAdd;
+if (mem != NULL)
+    {
+    lm->doMemoryAllocs = FALSE;
+    struct lmBlock *mb = mem;
+    mb->free = (char *)(mb+1);
+    mb->end = ((char *)mb) + blockSize;
+    mb->next = lm->blocks;
+    lm->blocks = mb;
+    }
+else
+    {
+    lm->doMemoryAllocs = TRUE;
     newBlock(lm, blockSize);
+    }
+
 return lm;
 }
 
+struct lm *lmInit(int blockSize)
+/* Create a local memory pool. */
+{
+return lmGuts(blockSize, NULL);
+}
+
+struct lm *lmInitWMem(void *mem, int blockSize)
+/* Create a local memory pool. */
+{
+return lmGuts(blockSize, mem);
+}
+
 void lmCleanup(struct lm **pLm)
 /* Clean up a local memory pool. */
 {
     struct lm *lm = *pLm;
     if (lm == NULL)
         return;
     *pLm = NULL;
     slFreeList(&lm->blocks);
     freeMem(lm);
 }
 
 size_t lmAvailable(struct lm *lm)
 // Returns currently available memory in pool
 {
 struct lmBlock *mb = lm->blocks;
@@ -88,31 +115,37 @@
 
 struct lmBlock *mb = lm->blocks;
 for (;mb != NULL;mb = mb->next)
     fullSize += (mb->end - (char *)(mb+1));
 
 return fullSize;
 }
 
 void *lmAlloc(struct lm *lm, size_t size)
 /* Allocate memory from local pool. */
 {
 struct lmBlock *mb = lm->blocks;
 void *ret;
 size_t memLeft = mb->end - mb->free;
 if (memLeft < size)
+    {
+    if (lm->doMemoryAllocs)
         mb = newBlock(lm, size);
+    else
+        errAbort("attempted local memory alloc in fixed size allocator");
+    }
+
 ret = mb->free;
 mb->free += ((size+lm->allignAdd)&lm->allignMask);
 if (mb->free > mb->end)
     mb->free = mb->end;
 return ret;
 }
 
 void *lmAllocMoreMem(struct lm *lm, void *pt, size_t oldSize, size_t newSize)
 /* Adjust memory size on a block, possibly relocating it.  If block is grown,
  * new memory is zeroed. */
 {
 struct lmBlock *mb = lm->blocks;
 // rare case that pointer is to last lm alloc, but still try.
 // Note this is the one place where the pointer gets reused and it is known to be in this lm
 if ((char *)pt + oldSize == mb->free