Index: /branches/jch-memory/psLib/src/sys/psMemory.c
===================================================================
--- /branches/jch-memory/psLib/src/sys/psMemory.c	(revision 10898)
+++ /branches/jch-memory/psLib/src/sys/psMemory.c	(revision 10899)
@@ -7,7 +7,8 @@
 *  @author Robert DeSonia, MHPCC
 *  @author Robert Lupton, Princeton University
+*  @author Joshua Hoblitt, University of Hawaii
 *
-*  @version $Revision: 1.88.2.9 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-01-03 22:25:33 $
+*  @version $Revision: 1.88.2.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-04 21:09:32 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -52,4 +53,6 @@
 P_PS_MEM_ABORT(__FILE__, __LINE__, __func__, name, __VA_ARGS__)
 
+// psErrorStackPrint() was specifically modified to be safe to call from inside
+// psMemory.c.
 #define P_PS_MEM_ABORT(filename, lineno, func, name, ...) \
 fprintf(stderr, "%s (%s:%d) ", func, filename, lineno); \
@@ -69,8 +72,38 @@
 fprintf(stderr, "\n");
 
-static bool badMemBlock(const psMemBlock* m, const char *funcName);
-static psMemBlock* lastMemBlockAllocated = NULL;
+#define PS_MEM_ABORT_CORRUPT(ptr) \
+PS_MEM_ABORT(file, "Memory corruption detected in block %lu, allocated at %s (%s:%d) by thread id %lu", \
+             (unsigned long)ptr->id, \
+             ptr->func, \
+             ptr->file, \
+             ptr->lineno,\
+             ptr->tid);
+
+static bool badMemBlock(const psMemBlock *memBlock);
+
+// pointer to the last mem block that was allocated
+static psMemBlock *lastMemBlockAllocated = NULL;
+
+// memBlockListMutex protects access to:
+//      lastMemBlockAllocated
+//      safeThreads
+//      memid
+//      memory_is_persistent
+//      "the linked list of mem blocks"
+//      p_psMemAllocID
+//      p_psMemFreeID
+//      memAllocCallback
+//      memFreeCallback
+//      memExhaustedCallback
+//
+// This is a fair ammount of stuff to protect with a single mutex but most of
+// these items are *VERY* low contention items.  The only item that should be
+// performance issue is "the linked list of mem blocks".  If this does become a
+// problem in production use of the list should be disabled as it is really a
+// debugging feature.
+//
+// XXX make the mem block list a build time option
+//
 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;
 
 //private boolean for enabling/disabling thread safety.  Default = enabled.
@@ -79,8 +112,4 @@
 // private boolean for deciding if allocated memory is persistent
 static bool memory_is_persistent = false;
-
-#ifdef PS_MEM_DEBUG
-static psMemBlock* deadBlockList;       // a place to put dead memBlocks in debug mode.
-#endif // #ifdef PS_MEM_DEBUG
 
 /**
@@ -103,5 +132,5 @@
  * isn't resignalled)
  */
-static psMemId memAllocCallbackDefault(const psMemBlock* ptr)
+static psMemId memAllocCallbackDefault(const psMemBlock *memBlock)
 {
     static psMemId incr = 0; // "p_psMemAllocID += incr"
@@ -110,24 +139,9 @@
 }
 
-static psMemId memFreeCallbackDefault(const psMemBlock* ptr)
+static psMemId memFreeCallbackDefault(const psMemBlock *memBlock)
 {
     static psMemId incr = 0; // "p_psMemFreeID += incr"
 
     return incr;
-}
-
-static void memProblemCallbackDefault(psMemBlock* ptr,
-                                      const char *file,
-                                      unsigned int lineno)
-{
-    if (ptr->refCounter < 1) {
-        PS_MEM_ERROR(PS_ERR_MEMORY_CORRUPTION, false,
-                     _("Block %lu, allocated at %s:%d, freed multiple times at %s:%d."),
-                     (unsigned long)ptr->id, ptr->file, ptr->lineno, file, lineno);
-    }
-
-    if (lineno > 0) {
-        PS_MEM_ABORT(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);
-    }
 }
 
@@ -137,11 +151,13 @@
  * N.b. If the block wasn't allocated by psAlloc, it will appear corrupted
  */
-static bool badMemBlock(const psMemBlock* m,
-                        const char *funcName)
-{
-    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
-    // we shouldn't call such things as p_psAlloc/p_psFree here.
-
-    if (m == NULL) {
+static bool badMemBlock(const psMemBlock *memBlock)
+{
+    // n.b. since this is called by psMemCheckCorruption while the memblock
+    // list is mutex locked, we shouldn't call such things as
+    // p_psAlloc/p_psFree here.
+
+    // ->nextBlock, & -> prevousBlock should not be looked at but this function
+    // as they make be changed out from underneath us by new memory allocation
+    if (memBlock == NULL) {
         PS_MEM_ERROR(PS_ERR_MEMORY_CORRUPTION, true,
                      _("NULL memory block found."));
@@ -149,22 +165,22 @@
     }
 
-    if (m->refCounter == 0) {
+    if (memBlock->refCounter == 0) {
         // using an unreferenced block of memory, are you?
         PS_MEM_ERROR(PS_ERR_MEMORY_CORRUPTION, true,
                      _("Memory block %lu was freed but still being used."),
-                     (unsigned long)m->id);
+                     (unsigned long)memBlock->id);
         return true;
     }
 
-    if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
+    if (memBlock->startblock != P_PS_MEMMAGIC || memBlock->endblock != P_PS_MEMMAGIC) {
         PS_MEM_ERROR(PS_ERR_MEMORY_CORRUPTION, true,
                      _("Memory block %lu is corrupted; buffer underflow detected."),
-                     (unsigned long)m->id);
+                     (unsigned long)memBlock->id);
         return true;
     }
-    if (*(psPtr *)((int8_t *) (m + 1) + m->userMemorySize) != P_PS_MEMMAGIC) {
+    if (*(psPtr *)((int8_t *) (memBlock + 1) + memBlock->userMemorySize) != P_PS_MEMMAGIC) {
         PS_MEM_ERROR(PS_ERR_MEMORY_CORRUPTION, true,
                      _("Memory block %lu is corrupted; buffer overflow detected."),
-                     (unsigned long)m->id);
+                     (unsigned long)memBlock->id);
         return true;
     }
@@ -178,5 +194,5 @@
  * with psMem{Alloc,Free}CallbackSet
  */
-static psMemId memAllocCallbackCheckCorruption(const psMemBlock *ptr)
+static psMemId memAllocCallbackCheckCorruption(const psMemBlock *memBlock)
 {
     static psMemId incr = 10; // "p_psMemAllocID += incr"
@@ -195,9 +211,10 @@
 static psMemAllocCallback memAllocCallback = memAllocCallbackDefault;
 static psMemFreeCallback memFreeCallback = memFreeCallbackDefault;
-static psMemProblemCallback memProblemCallback = memProblemCallbackDefault;
 static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault;
 
 psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     psMemExhaustedCallback old = memExhaustedCallback;
 
@@ -208,16 +225,5 @@
     }
 
-    return old;
-}
-
-psMemProblemCallback psMemProblemCallbackSet(psMemProblemCallback func)
-{
-    psMemProblemCallback old = memProblemCallback;
-
-    if (func != NULL) {
-        memProblemCallback = func;
-    } else {
-        memProblemCallback = memProblemCallbackDefault;
-    }
+    MUTEX_UNLOCK(&memBlockListMutex);
 
     return old;
@@ -234,4 +240,6 @@
 psMemId psMemAllocCallbackSetID(psMemId id)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     psMemId old = p_psMemAllocID;
 
@@ -243,4 +251,6 @@
     p_psMemAllocID = id;
 
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     return old;
 }
@@ -248,8 +258,12 @@
 psMemId psMemFreeCallbackSetID(psMemId id)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     psMemId old = p_psMemFreeID;
 
     p_psMemFreeID = id;
 
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     return old;
 }
@@ -257,4 +271,6 @@
 psMemAllocCallback psMemAllocCallbackSet(psMemAllocCallback func)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     psMemFreeCallback old = memAllocCallback;
 
@@ -265,4 +281,6 @@
     }
 
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     return old;
 }
@@ -270,4 +288,6 @@
 psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     psMemFreeCallback old = memFreeCallback;
 
@@ -278,4 +298,6 @@
     }
 
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     return old;
 }
@@ -291,9 +313,9 @@
 psMemId psMemGetLastId(void)
 {
-    MUTEX_LOCK(&memIdMutex);
+    MUTEX_LOCK(&memBlockListMutex);
 
     psMemId id = memid;
 
-    MUTEX_UNLOCK(&memIdMutex);
+    MUTEX_UNLOCK(&memBlockListMutex);
 
     return id;
@@ -308,9 +330,7 @@
     MUTEX_LOCK(&memBlockListMutex);
 
-    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock) {
-        if (badMemBlock(iter, __func__)) {
+    for (psMemBlock *memBlock = lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) {
+        if (badMemBlock(memBlock)) {
             nbad++;
-
-            memProblemCallback(iter, __func__, __LINE__);
 
             if (abort_on_error) {
@@ -334,7 +354,11 @@
 bool p_psMemAllocatePersistent(bool is_persistent)
 {
+    MUTEX_LOCK(&memBlockListMutex);
+
     const bool old = memory_is_persistent;
     memory_is_persistent = is_persistent;
 
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     return old;
 }
@@ -345,139 +369,138 @@
 psPtr p_psAlloc(size_t size,
                 const char *file,
-                unsigned int lineno)
-{
-
-    psMemBlock *ptr = NULL;
-
-    if (ptr == NULL) {
-        ptr = malloc(sizeof(psMemBlock) + size + sizeof(psPtr ));
-
-        if (ptr == NULL) {
-            ptr = memExhaustedCallback(size);
-            if (ptr == NULL) {
-                PS_MEM_ABORT(__func__, "Failed to allocate %zd bytes at %s:%d", size, file, lineno);
-            }
-        }
-
-        *(psPtr*)&ptr->startblock = P_PS_MEMMAGIC;
-        *(psPtr*)&ptr->endblock = P_PS_MEMMAGIC;
-        ptr->userMemorySize = size;
-    }
-
-    // increment the memory id safely.
-    MUTEX_LOCK(&memBlockListMutex);
-    *(psMemId* ) & ptr->id = ++memid;
-    MUTEX_UNLOCK(&memBlockListMutex);
-
-    ptr->file = file;
-    ptr->freeFunc = NULL;
-    ptr->persistent = memory_is_persistent;
-    *(psU32 *)&ptr->lineno = lineno;
-    *(psPtr *)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
-    ptr->previousBlock = NULL;
-
-    ptr->refCounter = 1;                   // one user so far
+                unsigned int lineno,
+                const char *func)
+{
+
+    psMemBlock *memBlock = malloc(sizeof(psMemBlock) + size + sizeof(psPtr));
+    if (memBlock == NULL) {
+        MUTEX_LOCK(&memBlockListMutex);
+        memBlock = memExhaustedCallback(size);
+        MUTEX_UNLOCK(&memBlockListMutex);
+        if (memBlock == NULL) {
+            PS_MEM_ABORT(__func__, "Failed to allocate %zd bytes at %s (%s:%d)", size, func, file, lineno);
+        }
+    }
+
+    // posts
+    *(psPtr*)&memBlock->startblock = P_PS_MEMMAGIC;
+    *(psPtr*)&memBlock->endblock = P_PS_MEMMAGIC;
+    *(psPtr *)((int8_t *) (memBlock + 1) + size) = P_PS_MEMMAGIC;
+
+    // size of memory allocated
+    memBlock->userMemorySize = size;
+
+    // alloc request by:
+    // thread
+    *(pthread_t *)&memBlock->tid = pthread_self();
+    // file
+    memBlock->file = file;
+    // line number
+    *(unsigned int *)&memBlock->lineno = (unsigned int)lineno;
+    // function
+    memBlock->func = func;
+
+    // free function
+    memBlock->freeFunc = NULL;
+
+    // persistent memory flag
+    memBlock->persistent = memory_is_persistent;
+
+    // this block will be the add as the last mem block in the list
+    memBlock->previousBlock = NULL;
+
+    // ref count
+    memBlock->refCounter = 1;                   // one user so far
 
     // need exclusive access of the memory block list now...
     MUTEX_LOCK(&memBlockListMutex);
 
+    // increment the memory id only after we've grabbed the memBlockListMutex
+    *(psMemId* )&memBlock->id = ++memid;
+
     // insert the new block to the front of the memBlock linked-list
-    ptr->nextBlock = lastMemBlockAllocated;
-    if (ptr->nextBlock != NULL) {
-        ptr->nextBlock->previousBlock = ptr;
-    }
-    lastMemBlockAllocated = ptr;
-
-    MUTEX_UNLOCK(&memBlockListMutex);
+    memBlock->nextBlock = lastMemBlockAllocated;
+    if (memBlock->nextBlock != NULL) {
+        memBlock->nextBlock->previousBlock = memBlock;
+    }
+    lastMemBlockAllocated = memBlock;
 
     // Did the user ask to be informed about this allocation?
-    if (ptr->id == p_psMemAllocID) {
-        p_psMemAllocID += memAllocCallback(ptr);
-    }
+    if (memBlock->id == p_psMemAllocID) {
+        // p_psMemAllocID can only be changed while the memBlockList mutex is
+        // held
+        p_psMemAllocID += memAllocCallback(memBlock);
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
     // And return the user the memory that they allocated
-    return ptr + 1;                        // user memory
-}
-
-psPtr p_psRealloc(psPtr vptr,
+    return memBlock + 1;                        // user memory
+}
+
+psPtr p_psRealloc(psPtr ptr,
                   size_t size,
                   const char *file,
-                  unsigned int lineno)
-{
-    if (vptr == NULL) {
-        return p_psAlloc(size, file, lineno);
-    }
-
-    psMemBlock *ptr = ((psMemBlock*)vptr) - 1;
-
-    if (badMemBlock(ptr, __func__) != 0) {
-        memProblemCallback(ptr, file, lineno);
-        PS_MEM_ABORT(file, "Realloc detected a memory corruption (id %lu @ %s:%d).",
-                     (unsigned long)ptr->id, ptr->file, ptr->lineno);
-    }
-
-    if (size == ptr->userMemorySize) {
+                  unsigned int lineno,
+                  const char *func)
+{
+    if (ptr == NULL) {
+        return p_psAlloc(size, file, lineno, func);
+    }
+
+    psMemBlock *memBlock = ((psMemBlock *)ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT(file, "Memory corruption detected in block %lu, allocated at %s (%s:%d) by thread id %lu",
+                     (unsigned long)memBlock->id,
+                     memBlock->func,
+                     memBlock->file,
+                     memBlock->lineno,
+                     memBlock->tid);
+    }
+
+    if (size == memBlock->userMemorySize) {
         // Nothing to do
-        return vptr;
+        return ptr;
     }
 
     // Reallocate the memory
 
-    MUTEX_LOCK(&memBlockListMutex);
-
-    bool isBlockLast = (ptr == lastMemBlockAllocated); // Is this the last block we allocated?
-    ptr = (psMemBlock *)realloc(ptr, sizeof(psMemBlock) + size + sizeof(psPtr));
-    if (ptr == NULL) {
-        ptr = memExhaustedCallback(size);
-        if (ptr == NULL) {
-            PS_MEM_ABORT(__func__, "Failed to reallocate %zd bytes at %s:%d", size, file, lineno);
-        }
-    }
-
-    ptr->userMemorySize = size;
-    *(psPtr *)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC;
-
-    if (isBlockLast) {
-        lastMemBlockAllocated = ptr;
+    memBlock = (psMemBlock *)realloc(memBlock, sizeof(psMemBlock) + size + sizeof(psPtr));
+    if (memBlock== NULL) {
+        MUTEX_LOCK(&memBlockListMutex);
+        memBlock = memExhaustedCallback(size);
+        if (memBlock == NULL) {
+            MUTEX_UNLOCK(&memBlockListMutex);
+            PS_MEM_ABORT(__func__, "Failed to reallocate %zd bytes at %s (%s:%d)", size, func, file, lineno);
+        }
+    }
+
+    memBlock->userMemorySize = size;
+    *(psPtr *)((int8_t *) (memBlock + 1) + size) = P_PS_MEMMAGIC;
+
+    MUTEX_LOCK(&memBlockListMutex);
+
+    // Is this the last block we allocated?
+    if (memBlock== lastMemBlockAllocated) {
+        lastMemBlockAllocated = memBlock;
     }
 
     // the block location may have changed, so fix the linked list addresses.
-    if (ptr->nextBlock != NULL) {
-        ptr->nextBlock->previousBlock = ptr;
-    }
-    if (ptr->previousBlock != NULL) {
-        ptr->previousBlock->nextBlock = ptr;
-    }
-
-    MUTEX_UNLOCK(&memBlockListMutex);
+    if (memBlock->nextBlock != NULL) {
+        memBlock->nextBlock->previousBlock = memBlock;
+    }
+    if (memBlock->previousBlock != NULL) {
+        memBlock->previousBlock->nextBlock = memBlock;
+    }
 
     // Did the user ask to be informed about this allocation?
-    if (ptr->id == p_psMemAllocID) {
-        p_psMemAllocID += memAllocCallback(ptr);
-    }
-
-    return ptr + 1;                    // usr memory
-}
-
-void p_psFree(psPtr vptr,
-              const char *filename,
-              unsigned int lineno)
-{
-    if (vptr == NULL) {
-        return;
-    }
-    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
-    if (ptr->refCounter < 1) {
-        psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
-
-        PS_MEM_ABORT(__func__,_("Block %lu, allocated at %s:%d, freed multiple times at %s:%d."),
-                     (unsigned long)ptr->id, ptr->file, ptr->lineno, filename, lineno);
-    }
-
-    if (badMemBlock(ptr, __func__) != 0) {
-        memProblemCallback(ptr, filename, lineno);
-        PS_MEM_ABORT(__func__,"Memory Corruption Detected.");
-    }
-
-    (void)p_psMemDecrRefCounter(vptr, filename, lineno);    // this handles the free, if required.
+    if (memBlock->id == p_psMemAllocID) {
+        p_psMemAllocID += memAllocCallback(memBlock);
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return memBlock + 1;                    // usr memory
 }
 
@@ -492,12 +515,12 @@
     psS32 nleak = 0;
     psS32 j = 0;
-    psMemBlock* topBlock = lastMemBlockAllocated;
-
-    MUTEX_LOCK(&memBlockListMutex);
-
-    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
-        if ( (iter->refCounter > 0) &&
-                ( (persistence) || (!persistence && !iter->persistent) ) &&
-                (iter->id >= id0)) {
+    psMemBlock *topBlock = lastMemBlockAllocated;
+
+    MUTEX_LOCK(&memBlockListMutex);
+
+    for (psMemBlock *memBlock = topBlock; memBlock != NULL; memBlock = memBlock->nextBlock) {
+        if ( (memBlock->refCounter > 0) &&
+                ( (persistence) || (!persistence && !memBlock->persistent) ) &&
+                (memBlock->id >= id0)) {
 
             nleak++;
@@ -508,5 +531,5 @@
                 }
 
-                fprintf(fd, "   %20s:%-4d %lu\n", iter->file, (int)iter->lineno, (unsigned long)iter->id);
+                fprintf(fd, "   %20s:%-4d %lu\n", memBlock->file, (int)memBlock->lineno, (unsigned long)memBlock->id);
             }
         }
@@ -519,13 +542,14 @@
     }
 
-    *array = p_psAlloc(nleak * sizeof(psMemBlock), __FILE__, __LINE__);
-    MUTEX_LOCK(&memBlockListMutex);
-
-    for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) {
-        if ( (iter->refCounter > 0) &&
-                ( (persistence) || (!persistence && !iter->persistent) ) &&
-                (iter->id >= id0)) {
-
-            (*array)[j++] = iter;
+    *array = psAlloc(nleak * sizeof(psMemBlock));
+
+    MUTEX_LOCK(&memBlockListMutex);
+
+    for (psMemBlock *memBlock = topBlock; memBlock != NULL; memBlock = memBlock ->nextBlock) {
+        if ( (memBlock->refCounter > 0) &&
+                ( (persistence) || (!persistence && !memBlock->persistent) ) &&
+                (memBlock->id >= id0)) {
+
+            (*array)[j++] = memBlock;
             if (j == nleak) {              // found them all
                 break;
@@ -546,49 +570,45 @@
 psReferenceCount psMemGetRefCounter(const psPtr ptr)
 {
-    psMemBlock* ptr2;
-    psU32 refCount;
-
     if (ptr == NULL) {
         return 0;
     }
 
-    ptr2 = ((psMemBlock* ) ptr) - 1;
-
-    if (badMemBlock(ptr2, __func__) != 0) {
-        memProblemCallback(ptr2, __func__, __LINE__);
-    }
-
-    refCount = ptr2->refCounter;
-
-    return refCount;
+    psMemBlock *memBlock = ((psMemBlock *) ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    return memBlock->refCounter;
 }
 
 // increment and return refCounter
-psPtr p_psMemIncrRefCounter(const psPtr vptr,
+psPtr p_psMemIncrRefCounter(const psPtr ptr,
                             const char *file,
                             psS32 lineno)
 {
-    psMemBlock* ptr;
-
-    if (vptr == NULL) {
-        return vptr;
-    }
-
-    ptr = ((psMemBlock* ) vptr) - 1;
-
-    if (badMemBlock(ptr, __func__)) {
-        memProblemCallback(ptr, file, lineno);
-    }
-
-    ptr->refCounter++;
+    if (ptr == NULL) {
+        return ptr;
+    }
+
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    memBlock->refCounter++;
 
     // Did the user ask to be informed about this allocation?
-    if (ptr->id == p_psMemAllocID) {
-        p_psMemAllocID += memAllocCallback(ptr);
-    }
-
-    return vptr;
-}
-
+    MUTEX_LOCK(&memBlockListMutex);
+    if (memBlock->id == p_psMemAllocID) {
+        p_psMemAllocID += memAllocCallback(memBlock);
+    }
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return ptr;
+}
+
+#if 0
 psPtr p_psMemSetRefCounter(psPtr vptr,
                            psReferenceCount count,
@@ -609,4 +629,5 @@
 
     if (badMemBlock(ptr, __func__)) {
+        (void)p_psMemDecrRefCounter(vptr, filename, lineno);
         memProblemCallback(ptr, file, lineno);
     }
@@ -620,52 +641,74 @@
     return vptr;
 }
+#endif
 
 // decrement and return refCounter
-psPtr p_psMemDecrRefCounter(psPtr vptr,
+psPtr p_psMemDecrRefCounter(psPtr ptr,
                             const char *file,
                             psS32 lineno)
 {
-    if (vptr == NULL) {
+    if (ptr == NULL) {
         return NULL;
     }
 
-    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
-
-    if (badMemBlock(ptr, __func__) != 0) {
-        memProblemCallback(ptr, file, lineno);
+    psMemBlock *memBlock = ((psMemBlock *) ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
         return NULL;
     }
 
+    if (memBlock->refCounter < 1) {
+        PS_MEM_ABORT(__func__,_("Block %lu, allocated at %s (%s:%d), freed multiple times at %s:%d."),
+                     (unsigned long)memBlock->id,
+                     memBlock->func,
+                     memBlock->file,
+                     memBlock->lineno,
+                     file,
+                     lineno);
+    }
+
+    // if we have multiple references, just decrement the count and return.
+    if (memBlock->refCounter > 1) {
+        memBlock->refCounter--;
+
+        // Did the user ask to be informed about this deallocation?
+        MUTEX_LOCK(&memBlockListMutex);
+        if (memBlock->id == p_psMemFreeID) {
+            p_psMemFreeID += memFreeCallback(memBlock);
+        }
+        MUTEX_UNLOCK(&memBlockListMutex);
+
+        return ptr;
+    }
+
+    // we can't invoke freeFunc() while we're holding memBlockListMutex as it
+    // may invoke psFree() itself
+    if (memBlock->freeFunc != NULL) {
+        memBlock->freeFunc(ptr);
+    }
+
+    MUTEX_LOCK(&memBlockListMutex);
+
     // Did the user ask to be informed about this deallocation?
-    if (ptr->id == p_psMemFreeID) {
+    if (memBlock->id == p_psMemFreeID) {
         p_psMemFreeID += memFreeCallback(ptr);
     }
 
-    if (ptr->refCounter > 1) {
-        ptr->refCounter--;                 // multiple references, just decrement the count.
-    } else {
-        if (ptr->freeFunc != NULL) {
-            ptr->freeFunc(vptr);
-        }
-
-        MUTEX_LOCK(&memBlockListMutex);
-
-        // cut the memBlock out of the memBlock list
-        if (ptr->nextBlock != NULL) {
-            ptr->nextBlock->previousBlock = ptr->previousBlock;
-        }
-        if (ptr->previousBlock != NULL) {
-            ptr->previousBlock->nextBlock = ptr->nextBlock;
-        }
-        if (lastMemBlockAllocated == ptr) {
-            lastMemBlockAllocated = ptr->nextBlock;
-        }
-
-        MUTEX_UNLOCK(&memBlockListMutex);
-
-        vptr = NULL;                       // since we freed it, make sure we return NULL.
-    }
-
-    return vptr;
+    // cut the memBlock out of the memBlock list
+    if (memBlock->nextBlock != NULL) {
+        memBlock->nextBlock->previousBlock = memBlock->previousBlock;
+    }
+    if (memBlock->previousBlock != NULL) {
+        memBlock->previousBlock->nextBlock = memBlock->nextBlock;
+    }
+    if (lastMemBlockAllocated == memBlock) {
+        lastMemBlockAllocated = memBlock->nextBlock;
+    }
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    // since we freed it, make sure we return NULL.
+    return NULL;
 }
 
@@ -677,12 +720,11 @@
     }
 
-    psMemBlock* PTR = ((psMemBlock* ) ptr) - 1;
-
-    if (badMemBlock(PTR, __func__) != 0) {
-        memProblemCallback(PTR, __func__, __LINE__);
-    }
-
-    PTR->freeFunc = freeFunc;
-
+    psMemBlock* memBlock = ((psMemBlock *)ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    memBlock->freeFunc = freeFunc;
 }
 
@@ -693,11 +735,11 @@
     }
 
-    psMemBlock* PTR = ((psMemBlock* ) ptr) - 1;
-
-    if (badMemBlock(PTR, __func__) != 0) {
-        memProblemCallback(PTR, __func__, __LINE__);
-    }
-
-    return PTR->freeFunc;
+    psMemBlock* memBlock = ((psMemBlock *)ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    return memBlock->freeFunc;
 }
 
@@ -705,267 +747,238 @@
                     psPtr ptr)
 {
-    //    PS_ASSERT_PTR(ptr, false);
+    if (!ptr) {
+        return false;
+    }
 
     switch(type) {
     case PS_DATA_ARRAY:
-        if ( psMemCheckArray(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckArray(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_BITSET:
-        if ( psMemCheckBitSet(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckBitSet(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_CUBE:
-        if ( psMemCheckCube(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckCube(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_FITS:
-        if ( psMemCheckFits(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckFits(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_HASH:
-        if ( psMemCheckHash(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckHash(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_HISTOGRAM:
-        if ( psMemCheckHistogram(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckHistogram(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_IMAGE:
-        if ( psMemCheckImage(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckImage(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_KERNEL:
-        if ( psMemCheckKernel(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckKernel(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_LINE:
-        if ( psMemCheckLine(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckLine(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_LIST:
-        if ( psMemCheckList(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckList(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_LOOKUPTABLE:
-        if ( psMemCheckLookupTable(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckLookupTable(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_METADATA:
-        if ( psMemCheckMetadata(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckMetadata(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_METADATAITEM:
-        if ( psMemCheckMetadataItem(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckMetadataItem(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_MINIMIZATION:
-        if ( psMemCheckMinimization(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckMinimization(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_PIXELS:
-        if ( psMemCheckPixels(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPixels(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_PLANE:
-        if ( psMemCheckPlane(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPlane(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_PLANEDISTORT:
-        if ( psMemCheckPlaneDistort(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPlaneDistort(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_PLANETRANSFORM:
-        if ( psMemCheckPlaneTransform(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPlaneTransform(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_POLYNOMIAL1D:
-        if ( psMemCheckPolynomial1D(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPolynomial1D(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_POLYNOMIAL2D:
-        if ( psMemCheckPolynomial2D(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPolynomial2D(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_POLYNOMIAL3D:
-        if ( psMemCheckPolynomial3D(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPolynomial3D(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_POLYNOMIAL4D:
-        if ( psMemCheckPolynomial4D(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckPolynomial4D(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_PROJECTION:
-        if ( psMemCheckProjection(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckProjection(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_REGION:
-        if ( psMemCheckRegion(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckRegion(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_SCALAR:
-        if ( psMemCheckScalar(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckScalar(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_SPHERE:
-        if ( psMemCheckSphere(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckSphere(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_SPHEREROT:
-        if ( psMemCheckSphereRot(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckSphereRot(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_SPLINE1D:
-        if ( psMemCheckSpline1D(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckSpline1D(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_STATS:
-        if ( psMemCheckStats(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckStats(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_STRING:
-        if ( psMemCheckString(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckString(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_TIME:
-        if ( psMemCheckTime(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckTime(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     case PS_DATA_VECTOR:
-        if ( psMemCheckVector(ptr) )
-            return true;
-        else {
-            PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
-                         "Incorrect pointer.  Datatypes do not match.\n");
-            break;
-        }
+        if (psMemCheckVector(ptr)) {
+            return true;
+        }
+        PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_VALUE, false,
+                     "Incorrect pointer.  Datatypes do not match.\n");
+        break;
     default:
         PS_MEM_ERROR(PS_ERR_BAD_PARAMETER_TYPE, true,
                      "Invalid datatype specified.\n");
     }
+
     return false;
 }
@@ -973,43 +986,54 @@
 bool psMemSetThreadSafety(bool safe)
 {
-    bool out = safeThreads;
+    MUTEX_LOCK(&memBlockListMutex);
+
+    bool oldState = safeThreads;
     safeThreads = safe;
-    return out;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return oldState;
 }
 
 bool psMemGetThreadSafety(void)
 {
-    return safeThreads;
-}
-
-bool p_psMemGetPersistent(psPtr vptr)
-{
-    if (vptr == NULL) {
+    MUTEX_LOCK(&memBlockListMutex);
+
+    bool oldState = safeThreads;
+
+    MUTEX_UNLOCK(&memBlockListMutex);
+
+    return oldState;
+}
+
+bool p_psMemGetPersistent(psPtr ptr)
+{
+    if (ptr == NULL) {
         return NULL;
     }
 
-    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
-
-    if (badMemBlock(ptr, __func__) != 0) {
-        memProblemCallback(ptr, __func__, __LINE__);
-    }
-
-    return ptr->persistent;
-}
-
-void p_psMemSetPersistent(psPtr vptr,
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    return memBlock->persistent;
+}
+
+void p_psMemSetPersistent(psPtr ptr,
                           bool value)
 {
-    if (vptr == NULL) {
+    if (ptr == NULL) {
         return;
     }
 
-    psMemBlock* ptr = ((psMemBlock* ) vptr) - 1;
-
-    if (badMemBlock(ptr, __func__) != 0) {
-        memProblemCallback(ptr, __func__, __LINE__);
-    }
-
-    ptr->persistent = value;
+    psMemBlock* memBlock = ((psMemBlock *) ptr) - 1;
+
+    if (badMemBlock(memBlock)) {
+        PS_MEM_ABORT_CORRUPT(memBlock);
+    }
+
+    memBlock->persistent = value;
 }
 
Index: /branches/jch-memory/psLib/src/sys/psMemory.h
===================================================================
--- /branches/jch-memory/psLib/src/sys/psMemory.h	(revision 10898)
+++ /branches/jch-memory/psLib/src/sys/psMemory.h	(revision 10899)
@@ -12,6 +12,6 @@
  *  @ingroup MemoryManagement
  *
- *  @version $Revision: 1.61.2.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-01-03 22:25:33 $
+ *  @version $Revision: 1.61.2.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-04 21:09:32 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -72,6 +72,8 @@
     size_t userMemorySize;             ///< the size of the user-portion of the memory block
     const psMemId id;                  ///< a unique ID for this allocation
+    const pthread_t tid;               ///< set from pthread_self();
     const char *file;                  ///< set from __FILE__ in e.g. p_psAlloc
     const unsigned int lineno;         ///< set from __LINE__ in e.g. p_psAlloc
+    const char *func;                  ///< set from __func__
     psReferenceCount refCounter;       ///< how many times pointer is referenced
     bool persistent;                   ///< marks if this non-user persistent data like error stack, etc.
@@ -137,11 +139,13 @@
 psPtr p_psAlloc(
     size_t size,                       ///< Size required
-    const char *filename,              ///< File of call
-    unsigned int lineno                ///< Line number of call
+    const char *filename,              ///< File of caller
+    unsigned int lineno,               ///< Line number of caller
+    const char *func                   ///< Function name of caller
 );
 
 /// Memory allocation. psAlloc sends file and line number to p_psAlloc.
 #ifndef SWIG
-#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
+#define psAlloc(size) \
+p_psAlloc(size, __FILE__, __LINE__, __func__)
 #endif // ! SWIG
 
@@ -256,11 +260,13 @@
     psPtr ptr,                         ///< Pointer to re-allocate
     size_t size,                       ///< Size required
-    const char *filename,              ///< File of call
-    unsigned int lineno                ///< Line number of call
+    const char *filename,              ///< File of caller
+    unsigned int lineno,               ///< Line number of caller
+    const char *func                   ///< Function name of caller
 );
 
 /// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
 #ifndef SWIG
-#define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
+#define psRealloc(ptr, size) \
+p_psRealloc(ptr, size, __FILE__, __LINE__, __func__)
 #endif // ! SWIG
 
@@ -276,14 +282,9 @@
 );
 #else // #ifdef DOXYGEN
-void p_psFree(
-    psPtr ptr,                         ///< Pointer to free
-    const char *filename,              ///< File of call
-    unsigned int lineno                ///< Line number of call
-);
 
 /// Free memory.  psFree sends file and line number to p_psFree.
 #ifndef SWIG
-//#define psFree(ptr) { p_psFree((psPtr)ptr, __FILE__, __LINE__); *(void**)&(ptr) = NULL; }
-#define psFree(ptr) { p_psFree((psPtr)ptr, __FILE__, __LINE__); }
+//#define psFree(ptr) { p_psMemDecrRefCounter((psPtr)ptr, __FILE__, __LINE__); *(void**)&(ptr) = NULL; }
+#define psFree(ptr) { p_psMemDecrRefCounter((psPtr)ptr, __FILE__, __LINE__); }
 #endif // ! SWIG
 
@@ -379,4 +380,5 @@
 #endif // !DOXYGEN
 
+#if 0 // psMemSetRefCounter
 /** Set reference counter and return the pointer
  *
@@ -404,4 +406,5 @@
 
 #endif // !DOXYGEN
+#endif // psMemSetRefCounter
 
 /** Set callback for problems.
