Index: /branches/eam_branches/ipp-20150616/Ohana/src/libohana/include/ohana_allocate.h
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/libohana/include/ohana_allocate.h	(revision 38490)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/libohana/include/ohana_allocate.h	(revision 38491)
@@ -29,5 +29,5 @@
 void  real_free (void *in);
 
-# define ohana_memcheck(X) ohana_memcheck_func (X);
+# define ohana_memcheck(X) ohana_memcheck_func (X)
 # define ohana_memdump(X) ohana_memdump_func (X);
 
@@ -56,5 +56,7 @@
 # else  /* below: not OHANA_MEMORY */
 
-# define ohana_memcheck(X) TRUE
+int   ohana_memcheck_noop (int mode);
+
+# define ohana_memcheck(X) ohana_memcheck_noop (X)
 # define ohana_memdump(X) /* NOP */
 void  real_free (void *in);
Index: /branches/eam_branches/ipp-20150616/Ohana/src/libohana/src/ohana_allocate.c
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/libohana/src/ohana_allocate.c	(revision 38490)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/libohana/src/ohana_allocate.c	(revision 38491)
@@ -4,4 +4,8 @@
 # include <stdint.h>
 # include <pthread.h>
+# include <string.h>
+
+# define TEST_SAVE_FREE_BLOCKS 1
+# define TEST_SAVE_DROP_BLOCKS 1
 
 # undef OHANA_MEMORY
@@ -23,8 +27,18 @@
   const char *func;	      // func (re)allocated 
   int line;		      // line (re)allocated
+  int freed;		      // memory has been freed
+  int dummy;		      // need to put endblock on the endpost
   uint32_t endblock;	      // endpost marker
 } Memblock;
 
 static Memblock *lastBlock = NULL;
+
+# if (TEST_SAVE_FREE_BLOCKS) 
+static Memblock *freeBlock = NULL;
+# endif
+
+# if (TEST_SAVE_DROP_BLOCKS) 
+static Memblock *dropBlock = NULL;
+# endif
 
 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -69,4 +83,8 @@
   new->line = line;
   new->func = func;
+  new->freed = FALSE;
+
+  // to be clean, zero out the memory
+  // memset (ptr, 0, new->size);
 
   // new memblock becomes the 'lastBlock':
@@ -99,5 +117,4 @@
 void *ohana_realloc (const char *file, int line, const char *func, void *in, size_t Nelem, size_t esize) {
 
-  void *ptr;		      // actual user memory allocated
   Memblock *old;	      // original memblock associated with user memory
   Memblock *new;	      // new memblock associated with user memory
@@ -106,5 +123,5 @@
   // just allocate if not previously allocated
   if (!in) {
-    ptr = ohana_malloc (file, line, func, Nelem, esize);
+    void *ptr = ohana_malloc (file, line, func, Nelem, esize);
     return ptr;
   }
@@ -131,18 +148,40 @@
   int isLast = (old == lastBlock);
 
+  // ask for new memory
+
+# if (TEST_SAVE_DROP_BLOCKS) 
+  // XXX for a test, we are going to always alloc a new block, copy the old data to the new block
+  // poison the old block, then free it
+  new = (Memblock *) malloc (sizeof(Memblock) + size + sizeof(void *));
+  if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
+  void *ptr_new = (char *) (new + 1);
+  void *ptr_old = (char *) (old + 1);
+  size_t copy_bytes = old->size < size ? old->size : size;
+  memcpy (ptr_new, ptr_old, copy_bytes);
+  memset (ptr_old, 0x7f, old->size);
+  new->nextBlock = old->nextBlock;
+  new->prevBlock = old->prevBlock;
+# else
   // ask for new memory
   // total size is : memblock + data + endpost
   new = (Memblock *) realloc (old, sizeof(Memblock) + size + sizeof(void *));
   if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d, %s)\n", file, line, func);
-  ptr = (char *) (new + 1);
+  void *ptr_new = (char *) (new + 1);
+# endif
   
-  // give the realloc location:
+  // set the end-post values
+  new->startblock = OHANA_MEMMAGIC;
+  new->endblock = OHANA_MEMMAGIC;
+  *(uint32_t *)(ptr_new + size) = OHANA_MEMMAGIC;
+
+  // set the memory metadata
   new->size = size; 
   new->file = file;
   new->line = line;
   new->func = func;
+  new->freed = FALSE;
 
   // update the endpost (the others were set originally
-  *(uint32_t *)(ptr + size) = OHANA_MEMMAGIC;
+  *(uint32_t *)(ptr_new + size) = OHANA_MEMMAGIC;
 
   // need to reset lastBlock in case we moved
@@ -159,7 +198,17 @@
   }
   
+  // XXX FOR TESTING, save the realloc blocks
+# if (TEST_SAVE_DROP_BLOCKS)
+  if (dropBlock) {
+    dropBlock->nextBlock = old;
+  }
+  old->nextBlock = NULL;
+  old->prevBlock = dropBlock;
+  dropBlock = old;
+# endif
+
   pthread_mutex_unlock(&memBlockListMutex);
 
-  return (ptr);
+  return (ptr_new);
 }
 
@@ -181,4 +230,7 @@
 
   ref = (Memblock *) in - 1;
+
+  if (ref->freed) ohana_memabort ("memory already freed (%s, %d, %s [%d bytes])\n", ref->file, ref->line, ref->func, ref->size);
+  ref->freed = TRUE;
 
   // fprintf (stderr, "  file: %s, line: %d, func: %s, size: %zd, addr: %zx\n", 
@@ -190,4 +242,5 @@
   Memblock *prevBlock = ref->prevBlock;
 
+  // remove this memBlock from the list
   if (nextBlock) {
     nextBlock->prevBlock = prevBlock;
@@ -200,9 +253,29 @@
   }
   
+  // XXX FOR TESTING, save the freed blocks
+# if (TEST_SAVE_FREE_BLOCKS)
+  if (freeBlock) {
+    freeBlock->nextBlock = ref;
+  }
+  ref->nextBlock = NULL;
+  ref->prevBlock = freeBlock;
+  freeBlock = ref;
+# endif
+
+  // pointer to the start of the user memory
+  void *ptr = (char *)(ref + 1);
+  memset (ptr, 0x77, ref->size);
+
   pthread_mutex_unlock(&memBlockListMutex);
   
+# if (!TEST_SAVE_FREE_BLOCKS)
   free (ref);
+# endif
 
   return;
+}
+
+int ohana_memcheck_noop (int allmemory) {
+  return TRUE;
 }
 
@@ -220,4 +293,5 @@
   size_t Ntotal = 0;
   size_t Nbytes = 0;
+  int status = TRUE;
 
   while (thisBlock) {
@@ -250,9 +324,106 @@
     thisBlock = thisBlock->prevBlock;
   }
+  fprintf (stderr, "%zd memory blocks allocated (%zd bytes total), %zd good, %zd bad\n", Ntotal, Nbytes, Ngood, Nbad);
+  if (Nbad) status = FALSE;
+
+# if (TEST_SAVE_FREE_BLOCKS) 
  
-  fprintf (stderr, "%zd memory blocks allocated (%zd bytes total), %zd good, %zd bad\n", Ntotal, Nbytes, Ngood, Nbad);
-
-  if (Nbad) return FALSE;
-  return TRUE;
+  thisBlock = freeBlock;
+
+  size_t Ngood_free  = 0;
+  size_t Nbad_free   = 0;
+  size_t Ntotal_free = 0;
+  size_t Nbytes_free = 0;
+
+  while (thisBlock) {
+
+    int i;
+    int good = TRUE;
+    
+    if (thisBlock->startblock != OHANA_MEMMAGIC) good = FALSE;
+    if (thisBlock->endblock != OHANA_MEMMAGIC) good = FALSE;
+
+    // pointer to the end of the user memory
+    char *ptr = (char *)(thisBlock + 1) + thisBlock->size;
+    uint32_t endpost = *(uint32_t *)ptr;
+    if (endpost != OHANA_MEMMAGIC) good = FALSE;
+
+    // pointer to the start of the user memory
+    ptr = (char *)(thisBlock + 1);
+    for (i = 0; i < thisBlock->size; i++, ptr++) {
+      if (*ptr != 0x77) good = FALSE;
+    }
+
+    // XXX keep checking even if memory is corrupted?
+    if (!good) {
+      if (Nbad_free < 1) {
+	fprintf (stderr, "memory corruption\n");
+      }
+      if (Nbad_free < 100) {
+	fprintf (stderr, "  file: %s, line: %d, func: %s\n", thisBlock->file, thisBlock->line, thisBlock->func);
+      }
+      Nbad_free ++;
+    } else {
+      Ngood_free ++;
+    }
+    Ntotal_free ++;
+    Nbytes_free += thisBlock->size;
+
+    thisBlock = thisBlock->prevBlock;
+  }
+  fprintf (stderr, "%zd memory blocks freed     (%zd bytes total), %zd good, %zd bad\n", Ntotal_free, Nbytes_free, Ngood_free, Nbad_free);
+  if (Nbad_free) status = FALSE;
+
+# endif
+ 
+# if (TEST_SAVE_DROP_BLOCKS)
+  thisBlock = dropBlock;
+
+  size_t Ngood_drop  = 0;
+  size_t Nbad_drop   = 0;
+  size_t Ntotal_drop = 0;
+  size_t Nbytes_drop = 0;
+
+  while (thisBlock) {
+
+    int i;
+    int good = TRUE;
+    
+    if (thisBlock->startblock != OHANA_MEMMAGIC) good = FALSE;
+    if (thisBlock->endblock != OHANA_MEMMAGIC) good = FALSE;
+
+    // pointer to the end of the user memory
+    char *ptr = (char *)(thisBlock + 1) + thisBlock->size;
+    uint32_t endpost = *(uint32_t *)ptr;
+    if (endpost != OHANA_MEMMAGIC) good = FALSE;
+
+    // pointer to the start of the user memory
+    ptr = (char *)(thisBlock + 1);
+    for (i = 0; i < thisBlock->size; i++, ptr++) {
+      if (*ptr != 0x7f) good = FALSE;
+    }
+
+    // XXX keep checking even if memory is corrupted?
+    if (!good) {
+      if (Nbad_drop < 1) {
+	fprintf (stderr, "memory corruption\n");
+      }
+      if (Nbad_drop < 100) {
+	fprintf (stderr, "  file: %s, line: %d, func: %s\n", thisBlock->file, thisBlock->line, thisBlock->func);
+      }
+      Nbad_drop ++;
+    } else {
+      Ngood_drop ++;
+    }
+    Ntotal_drop ++;
+    Nbytes_drop += thisBlock->size;
+
+    thisBlock = thisBlock->prevBlock;
+  }
+  fprintf (stderr, "%zd memory blocks dropped   (%zd bytes total), %zd good, %zd bad\n", Ntotal_drop, Nbytes_drop, Ngood_drop, Nbad_drop);
+  if (Nbad_drop) status = FALSE;
+# endif
+ 
+  return status;
 }
 
