Changeset 11265
- Timestamp:
- Jan 24, 2007, 12:14:48 PM (19 years ago)
- Location:
- trunk/psLib
- Files:
-
- 19 edited
-
src/sys/Makefile.am (modified) (1 diff)
-
src/sys/psAssert.h (modified) (1 diff)
-
src/sys/psConfigure.c (modified) (4 diffs)
-
src/sys/psError.c (modified) (6 diffs)
-
src/sys/psErrorCodes.c.in (modified) (4 diffs)
-
src/sys/psMemory.c (modified) (33 diffs)
-
src/sys/psMemory.h (modified) (20 diffs)
-
src/sys/psTrace.c (modified) (5 diffs)
-
src/sys/psType.h (modified) (2 diffs)
-
test/math/tap_psPolyFit1D.c (modified) (2 diffs)
-
test/math/tap_psPolyFit2D.c (modified) (2 diffs)
-
test/math/tap_psPolyFit3D.c (modified) (2 diffs)
-
test/math/tap_psPolyFit4D.c (modified) (2 diffs)
-
test/math/tap_psStats07.c (modified) (1 diff)
-
test/math/tap_psStats09.c (modified) (1 diff)
-
test/mathtypes/tap_psVectorSort_01.c (modified) (2 diffs)
-
test/mathtypes/tap_psVectorSort_02.c (modified) (2 diffs)
-
test/mathtypes/tap_psVectorSort_03.c (modified) (2 diffs)
-
test/mathtypes/tap_psVectorSort_04.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/sys/Makefile.am
r10980 r11265 15 15 psString.c \ 16 16 psTrace.c \ 17 psType.c \ 17 18 strcasestr.c 18 19 -
trunk/psLib/src/sys/psAssert.h
r11248 r11265 19 19 psMemBlock *mb = (psMemBlock*)(NAME) - 1; \ 20 20 if (mb->startblock != P_PS_MEMMAGIC || mb->endblock != P_PS_MEMMAGIC || \ 21 *(ps Ptr *)((int8_t *)(mb + 1) + mb->userMemorySize) != P_PS_MEMMAGIC) { \21 *(psU32 *)((char *)(mb + 1) + mb->userMemorySize) != P_PS_MEMMAGIC) { \ 22 22 psError(PS_ERR_MEMORY_CORRUPTION, false, \ 23 23 "Error: Pointer %s is corrupted or not on the PS memory system.", \ -
trunk/psLib/src/sys/psConfigure.c
r10487 r11265 13 13 * @author Robert DeSonia, MHPCC 14 14 * 15 * @version $Revision: 1.2 0$ $Name: not supported by cvs2svn $16 * @date $Date: 200 6-12-06 03:01:42$15 * @version $Revision: 1.21 $ $Name: not supported by cvs2svn $ 16 * @date $Date: 2007-01-24 22:14:48 $ 17 17 * 18 18 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 19 19 */ 20 21 #ifdef HAVE_CONFIG_H 22 # include "config.h" 23 #endif 24 20 25 #include <stdio.h> 21 26 #include <stdlib.h> … … 28 33 #include "psError.h" 29 34 #include "psConfigure.h" 30 31 #include "config.h"32 35 33 36 static char *memCheckName = NULL; // Filename to which to write results of mem check … … 58 61 } 59 62 60 // Print details of a memory problem to the appropriate file61 static void memoryProblem(const psMemBlock *ptr, // the pointer to the problematic memory block.62 const char *file, // the file in which the problem originated63 int lineno // the line number in which the problem originated64 )65 {66 fprintf(memCheckFile,67 "Memory corruption detected in memBlock %lu\n"68 "\tFile %s, line %d, size %zd\n"69 "\tPosts: %p %p %p\n",70 ptr->id, file, lineno, ptr->userMemorySize, ptr->startblock, ptr->endblock,71 (ptr + 1 + ptr->userMemorySize));72 }73 74 63 // Check the memory; intended for use on exit, but might be used elsewhere 75 64 void p_psMemoryCheck(void) … … 93 82 94 83 int nCorrupted; // Number of corrupted memory blocks 95 (void)psMemProblemCallbackSet((psMemProblemCallback)memoryProblem); // Set callback for corruption 96 nCorrupted = psMemCheckCorruption(false); 84 nCorrupted = psMemCheckCorruption(memCheckFile, false); 97 85 if (nCorrupted > 0) { 98 86 psError(PS_ERR_UNKNOWN, true, "%d memory blocks corrupted; list written to %s.\n", nCorrupted, memCheckName); -
trunk/psLib/src/sys/psError.c
r9730 r11265 11 11 * @author Eric Van Alst, MHPCC 12 12 * 13 * @version $Revision: 1.4 1$ $Name: not supported by cvs2svn $14 * @date $Date: 200 6-10-24 22:52:56$13 * @version $Revision: 1.42 $ $Name: not supported by cvs2svn $ 14 * @date $Date: 2007-01-24 22:14:48 $ 15 15 * 16 16 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 17 17 */ 18 19 #ifdef HAVE_CONFIG_H 20 # include "config.h" 21 #endif 18 22 19 23 #include <stdarg.h> … … 55 59 if (psArrayLength(errorStack) < MAX_ERROR_STACK_SIZE) { 56 60 // make the psErr persistent 57 p _psMemSetPersistent(err, true);58 p _psMemSetPersistent(err->msg, true);59 p _psMemSetPersistent(err->name, true);61 psMemSetPersistent(err, true); 62 psMemSetPersistent(err->msg, true); 63 psMemSetPersistent(err->name, true); 60 64 61 65 psArrayAdd(errorStack, 0, err); … … 85 89 // allocate the error stack 86 90 errorStack = psArrayAllocEmpty(MAX_ERROR_STACK_SIZE); 87 p _psMemSetPersistent(errorStack, true);88 p _psMemSetPersistent(errorStack->data, true);91 psMemSetPersistent(errorStack, true); 92 psMemSetPersistent(errorStack->data, true); 89 93 // store this threads error stack 90 94 // note that pthread_setspecifc() does not take a pointer as the first … … 93 97 psAbort(__func__, "pthread_setspecific() failed"); 94 98 } 99 } 100 101 return errorStack; 102 } 103 104 // This function serves the same purpose of psErrorStackGet() accept it does 105 // not alloc the error stack if it DOES NOT already exist. Unlike 106 // psErrorStackGet(), this function is NOT guarenteed to return a valid pointer 107 // and it's return status must be checked. 108 static psArray *psErrorStackGetNoAlloc(void) 109 { 110 // check to see if the error stack key has been initialized 111 pthread_mutex_lock(&lockErrorStack); 112 if (errorStackKeyInitialized == false) { 113 return NULL; 114 } 115 pthread_mutex_unlock(&lockErrorStack); 116 117 // check to see if the error stack for this thread has been allocated 118 psArray *errorStack = NULL; 119 if ((errorStack = pthread_getspecific(errorStack_key)) == NULL) { 120 return NULL; 95 121 } 96 122 … … 237 263 psErr *err = errorStack->data[i]; 238 264 239 p _psMemSetPersistent(err, false);240 p _psMemSetPersistent(err->msg, false);241 p _psMemSetPersistent(err->name, false);265 psMemSetPersistent(err, false); 266 psMemSetPersistent(err->msg, false); 267 psMemSetPersistent(err->name, false); 242 268 } 243 269 … … 260 286 } 261 287 288 // This function does not allocate any memory so it is safe to call from inside 289 // of psMemory.c. Do not allocate memory in function (or call any functions 290 // that do) without first removing it's use from psMemory.c. 262 291 void psErrorStackPrintV(FILE *fd, const char *format, va_list va) 263 292 { 264 psArray *errorStack = psErrorStackGet(); 293 psArray *errorStack = psErrorStackGetNoAlloc(); 294 // do nothing if the error stack has not been allocated 295 if (!errorStack) { 296 return; 297 } 265 298 266 299 vfprintf(fd, format, va); -
trunk/psLib/src/sys/psErrorCodes.c.in
r8233 r11265 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1. 6$ $Name: not supported by cvs2svn $10 * @date $Date: 200 6-08-08 23:39:59$9 * @version $Revision: 1.7 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2007-01-24 22:14:48 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 118 118 if (dynamicErrorCodes == NULL) { 119 119 dynamicErrorCodes = psListAlloc(NULL); 120 p _psMemSetPersistent(dynamicErrorCodes,true);120 psMemSetPersistent(dynamicErrorCodes,true); 121 121 122 p _psMemSetPersistent(dynamicErrorCodes->iterators,true);123 p _psMemSetPersistent(dynamicErrorCodes->iterators->data,true);122 psMemSetPersistent(dynamicErrorCodes->iterators,true); 123 psMemSetPersistent(dynamicErrorCodes->iterators->data,true); 124 124 for (int i = 0; i < dynamicErrorCodes->iterators->n;i++) { 125 p _psMemSetPersistent(dynamicErrorCodes->iterators->data[i],true);125 psMemSetPersistent(dynamicErrorCodes->iterators->data[i],true); 126 126 } 127 127 } … … 130 130 psErrorDescription* err = psErrorDescriptionAlloc( 131 131 errors[i].code, errors[i].description); 132 p _psMemSetPersistent(err,true);133 p _psMemSetPersistent((psPtr)err->description,true);132 psMemSetPersistent(err,true); 133 psMemSetPersistent((psPtr)err->description,true); 134 134 if (! psListAdd(dynamicErrorCodes, 135 135 PS_LIST_HEAD, … … 140 140 i); 141 141 } 142 p _psMemSetPersistent(dynamicErrorCodes->head,true);142 psMemSetPersistent(dynamicErrorCodes->head,true); 143 143 psFree(err); 144 144 } -
trunk/psLib/src/sys/psMemory.c
r10547 r11265 3 3 * @brief Contains the definitions for the memory management system 4 4 * 5 * psMemory.h has additional information and documentation of the routines found in this file. 5 * psMemory.h has additional information and documentation of the routines 6 * found in this file. 6 7 * 7 8 * @author Robert DeSonia, MHPCC 8 9 * @author Robert Lupton, Princeton University 10 * @author Joshua Hoblitt, University of Hawaii 9 11 * 10 * @version $Revision: 1.8 8$ $Name: not supported by cvs2svn $11 * @date $Date: 200 6-12-08 11:35:54$12 * @version $Revision: 1.89 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2007-01-24 22:14:48 $ 12 14 * 13 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 14 16 */ 17 18 #if HAVE_CONFIG_H 19 # include "config.h" 20 #endif 15 21 16 22 #define PS_ALLOW_MALLOC // we're allowed to call malloc() … … 22 28 #include <assert.h> 23 29 30 #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE) 31 # include <execinfo.h> 32 #endif 33 24 34 #include "psMemory.h" 25 #include "psError.h" 26 #include "psAssert.h" 27 #include "psAbort.h" 28 #include "psLogMsg.h" 29 #include "psBitSet.h" 30 #include "psFits.h" 31 #include "psPixels.h" 32 #include "psSphereOps.h" 33 #include "psMinimizeLMM.h" 34 #include "psImageConvolve.h" 35 #include "psTime.h" 36 #include "psLine.h" 37 #include "psRegion.h" 38 #include "psHistogram.h" 39 40 #define P_PS_LARGE_BLOCK_SIZE 65536 // size where under, we try to recycle 41 42 static psS32 checkMemBlock(const psMemBlock* m, const char *funcName); 43 static psMemBlock* lastMemBlockAllocated = NULL; 35 #include "psError.h" // for psErrorStackPrint() only 36 37 #define MUTEX_LOCK(mutexPtr) \ 38 if (safeThreads) { \ 39 pthread_mutex_lock(mutexPtr); \ 40 } 41 42 #define MUTEX_UNLOCK(mutexPtr) \ 43 if (safeThreads) { \ 44 pthread_mutex_unlock(mutexPtr); \ 45 } 46 47 // psAbort() calls functions that call psAlloc() so it is *UNSAFE* to use it 48 // from within the memory subsystem. Previous implementations tried to do 49 // this and would deadlock while trying to allocate memory. 50 // 51 // Note that psError() is also *UNSAFE* to use from within the memory 52 // subsystem. 53 #define PS_MEM_ABORT(name, ...) \ 54 P_PS_MEM_ABORT(__FILE__, __LINE__, __func__, name, __VA_ARGS__) 55 56 // psErrorStackPrint() was specifically modified to be safe to call from inside 57 // psMemory.c. 58 #define P_PS_MEM_ABORT(filename, lineno, func, name, ...) \ 59 fprintf(stderr, "%s (%s:%d) ", func, filename, lineno); \ 60 fprintf(stderr, __VA_ARGS__);\ 61 psErrorStackPrint(stderr, "\nAborting. Error stack:\n"); \ 62 fprintf(stderr, "\n");\ 63 abort(); 64 65 #define HANDLE_BAD_BLOCK(memBlock, file, lineo, func) \ 66 if (isBadMemBlock(stderr, memBlock, file, lineo, func)) { \ 67 PS_MEM_ABORT(__func__, "Unsafe to Continue\n"); \ 68 } 69 70 static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineo, const char *func); 71 72 // pointer to the last mem block that was allocated 73 static psMemBlock *lastMemBlockAllocated = NULL; 74 75 // memBlockListMutex protects access to: 76 // lastMemBlockAllocated 77 // safeThreads 78 // memid 79 // memory_is_persistent 80 // "the linked list of mem blocks" 81 // p_psMemAllocID 82 // p_psMemFreeID 83 // memAllocCallback 84 // memFreeCallback 85 // memExhaustedCallback 86 // 87 // This is a fair ammount of stuff to protect with a single mutex but most of 88 // these items are *VERY* low contention items. The only item that should be 89 // performance issue is "the linked list of mem blocks". If this does become a 90 // problem in production use of the list should be disabled as it is really a 91 // debugging feature. 92 // 93 // XXX make the mem block list a build time option 94 // 44 95 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER; 45 static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;46 96 47 97 //private boolean for enabling/disabling thread safety. Default = enabled. … … 51 101 static bool memory_is_persistent = false; 52 102 53 #ifdef PS_MEM_USE_RECYCLE // Only use recycling if this is set54 #define N_RECYCLE_BINS 14 // number of recycle bins55 #define MAX_RECYCLE 100 // Maximum number permitted in a recycle bin56 static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER; // Mutex for recycle bins57 static const psS32 recycleBinSize[N_RECYCLE_BINS] = // Size of each bin58 {59 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE60 };61 // N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops)62 static psS32 recycleBinNums[N_RECYCLE_BINS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Number in each bin63 static psMemBlock* recycleMemBlockList[N_RECYCLE_BINS] = // Contents of the bins64 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };65 #endif // #ifdef PS_MEM_USE_RECYCLE66 67 #ifdef PS_MEM_DEBUG68 static psMemBlock* deadBlockList; // a place to put dead memBlocks in debug mode.69 #endif // #ifdef PS_MEM_DEBUG70 71 103 /** 72 104 * Unique ID for allocated blocks … … 79 111 static psPtr memExhaustedCallbackDefault(size_t size) 80 112 { 81 #if PS_MEM_USE_RECYCLE82 psPtr ptr = NULL;83 if (safeThreads) {84 pthread_mutex_lock(&recycleMemBlockListMutex);85 }86 // Attempt to free up everything I can find so I can alloc my ptr87 int bin = N_RECYCLE_BINS - 1; // Recycle bin88 89 while (bin >= 0 && ptr == NULL) {90 while (recycleMemBlockList[bin] != NULL && ptr == NULL) {91 psMemBlock *old = recycleMemBlockList[bin];92 recycleMemBlockList[bin] = recycleMemBlockList[bin]->nextBlock;93 free(old);94 ptr = malloc(size);95 }96 bin--;97 }98 99 if (safeThreads) {100 pthread_mutex_unlock(&recycleMemBlockListMutex);101 }102 return ptr;103 #else // #ifdef PS_MEM_USE_RECYCLE104 105 113 return NULL; 106 #endif // #ifdef PS_MEM_USE_RECYCLE107 114 } 108 115 … … 113 120 * isn't resignalled) 114 121 */ 115 static psMemId memAllocCallbackDefault(const psMemBlock * ptr)122 static psMemId memAllocCallbackDefault(const psMemBlock *memBlock) 116 123 { 117 124 static psMemId incr = 0; // "p_psMemAllocID += incr" … … 120 127 } 121 128 122 static psMemId memFreeCallbackDefault(const psMemBlock * ptr)129 static psMemId memFreeCallbackDefault(const psMemBlock *memBlock) 123 130 { 124 131 static psMemId incr = 0; // "p_psMemFreeID += incr" 125 132 126 133 return incr; 127 }128 129 static void memProblemCallbackDefault(psMemBlock* ptr,130 const char *file,131 unsigned int lineno)132 {133 if (ptr->refCounter < 1) {134 psError(PS_ERR_MEMORY_CORRUPTION, false,135 _("Block %lu, allocated at %s:%d, freed multiple times at %s:%d."),136 (unsigned long)ptr->id, ptr->file, ptr->lineno, file, lineno);137 }138 139 if (lineno > 0) {140 psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);141 }142 134 } 143 135 … … 147 139 * N.b. If the block wasn't allocated by psAlloc, it will appear corrupted 148 140 */ 149 static psS32 checkMemBlock(const psMemBlock* m, 150 const char *funcName) 151 { 152 // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked, 153 // we shouldn't call such things as p_psAlloc/p_psFree here. 154 155 if (m == NULL) { 156 psError(PS_ERR_MEMORY_CORRUPTION, true, 157 _("NULL memory block found.")); 158 return 1; 159 } 160 161 if (m->refCounter == 0) { 141 static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineno, const char *func) 142 { 143 // n.b. since this is called by psMemCheckCorruption while the memblock 144 // list is mutex locked, we shouldn't call such things as 145 // p_psAlloc/p_psFree here. 146 147 bool bad = false; 148 bool blockPrinted = false; 149 150 if (memBlock == NULL) { 151 fprintf(output, _("NULL memory block.\n" 152 "Caught in %s at (%s:%d.).\n\n"), func, file, lineno); 153 // return now as we can't do anything else 154 return true; 155 } 156 157 #if 0 158 // Currently psAlloc()/psRealloc() will blindly create memBlock's with a 159 // size of 0. This test is in here to check if this is really 160 // happening/being use as a feature in the wild. 161 if (memBlock->userMemorySize < 1) { 162 psMemBlockPrint(output, memBlock); 163 blockPrinted = true; 164 fprintf(output, _("\n\tMemory block has a size of less than 1.\n")); 165 bad = true; 166 } 167 #endif 168 169 if (memBlock->refCounter < 1) { 162 170 // using an unreferenced block of memory, are you? 163 psError(PS_ERR_MEMORY_CORRUPTION, true, 164 _("Memory block %lu was freed but still being used."), 165 (unsigned long)m->id); 166 return 1; 167 } 168 169 if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) { 170 psError(PS_ERR_MEMORY_CORRUPTION, true, 171 _("Memory block %lu is corrupted; buffer underflow detected."), 172 (unsigned long)m->id); 173 return 1; 174 } 175 if (*(psPtr *)((int8_t *) (m + 1) + m->userMemorySize) != P_PS_MEMMAGIC) { 176 psError(PS_ERR_MEMORY_CORRUPTION, true, 177 _("Memory block %lu is corrupted; buffer overflow detected."), 178 (unsigned long)m->id); 179 return 1; 180 } 181 182 return 0; 171 psMemBlockPrint(output, memBlock); 172 blockPrinted = true; 173 fprintf(output, _("\n\tMemory block was freed but still being used.\n")); 174 bad = true; 175 } 176 177 if (memBlock->startblock != P_PS_MEMMAGIC || memBlock->endblock != P_PS_MEMMAGIC) { 178 if (!blockPrinted) { 179 psMemBlockPrint(output, memBlock); 180 blockPrinted = true; 181 } 182 fprintf(output, _("\n\tMemory block is corrupted; buffer underflow detected.\n")); 183 bad = true; 184 } 185 186 if (*(psU32 *)((char *)(memBlock + 1) + memBlock->userMemorySize) != P_PS_MEMMAGIC) { 187 if (!blockPrinted) { 188 psMemBlockPrint(output, memBlock); 189 blockPrinted = true; 190 } 191 fprintf(output, _("\n\tMemory block is corrupted; buffer overflow detected.\n")); 192 bad = true; 193 } 194 195 // XXX ->nextBlock, & -> prevousBlock really should not be looked at by 196 // this function as they may be changed out from underneath us by new 197 // memory allocation. However, the memBlock itself shouldn't go away (end 198 // users responsiblity) so all we're really risking is a garbage value. 199 200 if (memBlock == memBlock->nextBlock) { 201 if (!blockPrinted) { 202 psMemBlockPrint(output, memBlock); 203 blockPrinted = true; 204 } 205 fprintf(output, _("\n\tMemory block's ->nextBlock pointer refers to itself.\n")); 206 bad = true; 207 } 208 209 if (memBlock == memBlock->previousBlock) { 210 if (!blockPrinted) { 211 psMemBlockPrint(output, memBlock); 212 blockPrinted = true; 213 } 214 fprintf(output, _("\n\tMemory block's ->previousBlock pointer refers to itself.\n")); 215 bad = true; 216 } 217 218 if (bad) { 219 fprintf(output, _("\tCaught in %s at (%s:%d).\n\n"), func, file, lineno); 220 } 221 222 return bad; 183 223 } 184 224 … … 188 228 * with psMem{Alloc,Free}CallbackSet 189 229 */ 190 static psMemId memAllocCallbackCheckCorruption(const psMemBlock * ptr)230 static psMemId memAllocCallbackCheckCorruption(const psMemBlock *memBlock) 191 231 { 192 232 static psMemId incr = 10; // "p_psMemAllocID += incr" 193 bool abort_on_error = false; 194 195 if (psMemCheckCorruption(abort_on_error) > 0) { 196 fprintf(stderr,"Detected memory corruption\n"); // somewhere to set a breakpoint 233 234 if (psMemCheckCorruption(stderr, false) > 0) { 235 fprintf(stderr, "Detected memory corruption\n"); // somewhere to set a breakpoint 197 236 } 198 237 … … 205 244 static psMemAllocCallback memAllocCallback = memAllocCallbackDefault; 206 245 static psMemFreeCallback memFreeCallback = memFreeCallbackDefault; 207 static psMemProblemCallback memProblemCallback = memProblemCallbackDefault;208 246 static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault; 209 247 210 248 psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func) 211 249 { 250 MUTEX_LOCK(&memBlockListMutex); 251 212 252 psMemExhaustedCallback old = memExhaustedCallback; 213 253 … … 218 258 } 219 259 220 return old; 221 } 222 223 psMemProblemCallback psMemProblemCallbackSet(psMemProblemCallback func) 224 { 225 psMemProblemCallback old = memProblemCallback; 226 227 if (func != NULL) { 228 memProblemCallback = func; 229 } else { 230 memProblemCallback = memProblemCallbackDefault; 231 } 260 MUTEX_UNLOCK(&memBlockListMutex); 232 261 233 262 return old; … … 244 273 psMemId psMemAllocCallbackSetID(psMemId id) 245 274 { 275 MUTEX_LOCK(&memBlockListMutex); 276 246 277 psMemId old = p_psMemAllocID; 247 278 … … 253 284 p_psMemAllocID = id; 254 285 286 MUTEX_UNLOCK(&memBlockListMutex); 287 255 288 return old; 256 289 } … … 258 291 psMemId psMemFreeCallbackSetID(psMemId id) 259 292 { 293 MUTEX_LOCK(&memBlockListMutex); 294 260 295 psMemId old = p_psMemFreeID; 261 296 262 297 p_psMemFreeID = id; 263 298 299 MUTEX_UNLOCK(&memBlockListMutex); 300 264 301 return old; 265 302 } … … 267 304 psMemAllocCallback psMemAllocCallbackSet(psMemAllocCallback func) 268 305 { 306 MUTEX_LOCK(&memBlockListMutex); 307 269 308 psMemFreeCallback old = memAllocCallback; 270 309 … … 275 314 } 276 315 316 MUTEX_UNLOCK(&memBlockListMutex); 317 277 318 return old; 278 319 } … … 280 321 psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func) 281 322 { 323 MUTEX_LOCK(&memBlockListMutex); 324 282 325 psMemFreeCallback old = memFreeCallback; 283 326 … … 288 331 } 289 332 333 MUTEX_UNLOCK(&memBlockListMutex); 334 290 335 return old; 291 336 } … … 301 346 psMemId psMemGetLastId(void) 302 347 { 303 if (safeThreads) { 304 pthread_mutex_lock(&memIdMutex); 305 } 348 MUTEX_LOCK(&memBlockListMutex); 306 349 307 350 psMemId id = memid; 308 351 309 if (safeThreads) { 310 pthread_mutex_unlock(&memIdMutex); 311 } 352 MUTEX_UNLOCK(&memBlockListMutex); 312 353 313 354 return id; 314 355 } 315 356 316 int psMemCheckCorruption(bool abort_on_error) 317 { 357 int psMemCheckCorruption(FILE *output, bool abort_on_error) 358 { 359 // get exclusive access to the memBlock list to avoid it changing on us 360 // while we use it. 361 MUTEX_LOCK(&memBlockListMutex); 362 318 363 psS32 nbad = 0; // number of bad blocks 319 psBool failure = false; 320 321 // get exclusive access to the memBlock list to avoid it changing on us while we use it. 322 // pthread_mutex_lock(&memBlockListMutex); 323 324 for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock) { 325 if (safeThreads) { 326 pthread_mutex_unlock(&memBlockListMutex); 327 } 328 failure = checkMemBlock(iter, __func__); 329 if (safeThreads) { 330 pthread_mutex_lock(&memBlockListMutex); 331 } 332 if ( failure ) { 364 for (psMemBlock *memBlock = lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) { 365 if (isBadMemBlock(output, memBlock, __FILE__, __LINE__, __func__)) { 333 366 nbad++; 334 335 memProblemCallback(iter, __func__, __LINE__);336 367 337 368 if (abort_on_error) { 338 369 // release the lock on the memblock list 339 if (safeThreads) { 340 pthread_mutex_unlock(&memBlockListMutex); 341 } 342 psAbort(__func__, "Detected memory corruption"); 370 MUTEX_UNLOCK(&memBlockListMutex); 371 PS_MEM_ABORT(__func__, "Detected memory corruption"); 343 372 return nbad; 344 373 } … … 347 376 348 377 // release the lock on the memblock list 349 if (safeThreads) { 350 pthread_mutex_unlock(&memBlockListMutex); 351 } 378 MUTEX_UNLOCK(&memBlockListMutex); 379 352 380 return nbad; 353 381 } … … 358 386 bool p_psMemAllocatePersistent(bool is_persistent) 359 387 { 388 MUTEX_LOCK(&memBlockListMutex); 389 360 390 const bool old = memory_is_persistent; 361 391 memory_is_persistent = is_persistent; 362 392 393 MUTEX_UNLOCK(&memBlockListMutex); 394 363 395 return old; 364 396 } 365 366 #ifdef PS_MEM_USE_RECYCLE367 // Return the appropriate recycle bin number368 static int getRecycleBin(size_t size)369 {370 if (size >= P_PS_LARGE_BLOCK_SIZE) {371 return N_RECYCLE_BINS;372 }373 int binNum = 0; // Recycle bin number374 while (size > recycleBinSize[binNum]) {375 binNum++;376 }377 return binNum;378 }379 380 // Push a pointer onto the recycle bin381 static void recyclePush(psMemBlock *mb, // Pointer to push382 int bin // Recycling bin383 )384 {385 assert(mb);386 assert(bin < N_RECYCLE_BINS);387 388 mb->previousBlock = NULL;389 390 if (safeThreads) {391 pthread_mutex_lock(&recycleMemBlockListMutex);392 }393 394 mb->nextBlock = recycleMemBlockList[bin];395 if (recycleMemBlockList[bin] != NULL) {396 recycleMemBlockList[bin]->previousBlock = mb;397 }398 recycleMemBlockList[bin] = mb;399 recycleBinNums[bin]++;400 401 if (safeThreads) {402 pthread_mutex_unlock(&recycleMemBlockListMutex);403 }404 405 return;406 }407 408 // Pop a pointer from the recycle bin409 static psMemBlock *recyclePop(int bin // Recycling bin410 )411 {412 if (bin >= N_RECYCLE_BINS) {413 return NULL;414 }415 416 if (safeThreads) {417 pthread_mutex_lock(&recycleMemBlockListMutex);418 }419 420 psMemBlock *mb = recycleMemBlockList[bin]; // Pointer popped from recycle bin421 422 if (mb) {423 // We pull it off the list424 recycleMemBlockList[bin] = mb->nextBlock;425 if (recycleMemBlockList[bin] != NULL) {426 recycleMemBlockList[bin]->previousBlock = NULL;427 }428 recycleBinNums[bin]--;429 }430 431 if (safeThreads) {432 pthread_mutex_unlock(&recycleMemBlockListMutex);433 }434 435 return mb;436 }437 #endif // #ifdef PS_MEM_USE_RECYCLE438 397 439 398 /* … … 442 401 psPtr p_psAlloc(size_t size, 443 402 const char *file, 444 unsigned int lineno) 445 { 446 447 psMemBlock *ptr = NULL; 448 449 #ifdef PS_MEM_USE_RECYCLE 450 // Are we in one of the recycle bins? 451 int bin = getRecycleBin(size); 452 if (bin < N_RECYCLE_BINS) { 453 size = recycleBinSize[bin]; // round-up size to next sized bin. 454 ptr = recyclePop(bin); // grab out of the recycle bin 455 } 456 #endif // #ifdef PS_MEM_USE_RECYCLE 457 458 if (ptr == NULL) { 459 ptr = malloc(sizeof(psMemBlock) + size + sizeof(psPtr )); 460 461 if (ptr == NULL) { 462 ptr = memExhaustedCallback(size); 463 if (ptr == NULL) { 464 psAbort(__func__, "Failed to allocate %zd bytes at %s:%d", size, file, lineno); 465 } 466 } 467 468 *(psPtr*)&ptr->startblock = P_PS_MEMMAGIC; 469 *(psPtr*)&ptr->endblock = P_PS_MEMMAGIC; 470 ptr->userMemorySize = size; 471 if (safeThreads) { 472 pthread_mutex_init(&ptr->refCounterMutex, NULL); 473 } 474 } 475 // increment the memory id safely. 476 if (safeThreads) { 477 pthread_mutex_lock(&memBlockListMutex); 478 } 479 *(psMemId* ) & ptr->id = ++memid; 480 if (safeThreads) { 481 pthread_mutex_unlock(&memBlockListMutex); 482 } 483 ptr->file = file; 484 ptr->freeFunc = NULL; 485 ptr->persistent = memory_is_persistent; 486 *(psU32 *)&ptr->lineno = lineno; 487 *(psPtr *)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC; 488 ptr->previousBlock = NULL; 489 490 ptr->refCounter = 1; // one user so far 403 unsigned int lineno, 404 const char *func) 405 { 406 407 psMemBlock *memBlock = malloc(sizeof(psMemBlock) + size + sizeof(psPtr)); 408 if (memBlock == NULL) { 409 MUTEX_LOCK(&memBlockListMutex); 410 memBlock = memExhaustedCallback(size); 411 MUTEX_UNLOCK(&memBlockListMutex); 412 if (memBlock == NULL) { 413 PS_MEM_ABORT(__func__, "Failed to allocate %zd bytes at %s (%s:%d)", size, func, file, lineno); 414 } 415 } 416 417 // posts 418 *(psU32 *)&memBlock->startblock = P_PS_MEMMAGIC; 419 *(psU32 *)&memBlock->endblock = P_PS_MEMMAGIC; 420 *(psU32 *)((char *) (memBlock + 1) + size) = P_PS_MEMMAGIC; 421 422 // size of memory allocated 423 memBlock->userMemorySize = size; 424 425 // alloc request by: 426 // thread 427 *(pthread_t *)&memBlock->tid = pthread_self(); 428 // file 429 memBlock->file = file; 430 // line number 431 *(unsigned int *)&memBlock->lineno = (unsigned int)lineno; 432 // function 433 memBlock->func = func; 434 435 #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE) 436 #define BACKTRACE_BUFFER_SIZE 32 437 // psMemBlock.func is a 'const char *', so basically we're going to abuse 438 // that and treat it as a void ** to carry around backtrace information. 439 // psMemBlock is not ifdef'd to make sure that psMemBlock is always the 440 // same size & layout reguardless of the pslib .so that's being linked 441 // against 442 void **bt = malloc(BACKTRACE_BUFFER_SIZE * sizeof(void *)); 443 if (bt == NULL) { 444 PS_MEM_ABORT(__func__, "Failed to allocate memmory for backtrace buffer: %zd bytes at %s (%s:%d)", 32 * sizeof(void *), func, file, lineno); 445 } 446 *(size_t *)&memBlock->backtraceSize = backtrace(bt, BACKTRACE_BUFFER_SIZE); 447 *(void ***)&memBlock->backtrace = bt; 448 #endif // ifdef HAVE_BACKTRACE 449 450 // free function 451 memBlock->freeFunc = NULL; 452 453 // persistent memory flag 454 memBlock->persistent = memory_is_persistent; 455 456 // this block will be add as the last mem block in the list 457 memBlock->previousBlock = NULL; 458 459 // ref count 460 memBlock->refCounter = 1; // one user so far 491 461 492 462 // need exclusive access of the memory block list now... 493 if (safeThreads) { 494 pthread_mutex_lock(&memBlockListMutex); 495 } 463 MUTEX_LOCK(&memBlockListMutex); 464 465 // increment the memory id only after we've grabbed the memBlockListMutex 466 *(psMemId* )&memBlock->id = ++memid; 496 467 497 468 // insert the new block to the front of the memBlock linked-list 498 ptr->nextBlock = lastMemBlockAllocated; 499 if (ptr->nextBlock != NULL) { 500 ptr->nextBlock->previousBlock = ptr; 501 } 502 lastMemBlockAllocated = ptr; 503 504 if (safeThreads) { 505 pthread_mutex_unlock(&memBlockListMutex); 506 } 469 memBlock->nextBlock = lastMemBlockAllocated; 470 if (memBlock->nextBlock != NULL) { 471 memBlock->nextBlock->previousBlock = memBlock; 472 } 473 lastMemBlockAllocated = memBlock; 507 474 508 475 // Did the user ask to be informed about this allocation? 509 if (ptr->id == p_psMemAllocID) { 510 p_psMemAllocID += memAllocCallback(ptr); 511 } 476 if (memBlock->id == p_psMemAllocID) { 477 // p_psMemAllocID can only be changed while the memBlockList mutex is 478 // held 479 p_psMemAllocID += memAllocCallback(memBlock); 480 } 481 482 MUTEX_UNLOCK(&memBlockListMutex); 483 512 484 // And return the user the memory that they allocated 513 return ptr+ 1; // user memory514 } 515 516 psPtr p_psRealloc(psPtr vptr,485 return memBlock + 1; // user memory 486 } 487 488 psPtr p_psRealloc(psPtr ptr, 517 489 size_t size, 518 490 const char *file, 519 unsigned int lineno) 520 { 521 if (vptr == NULL) { 522 return p_psAlloc(size, file, lineno); 523 } 524 525 psMemBlock *ptr = ((psMemBlock*)vptr) - 1; 526 527 if (checkMemBlock(ptr, __func__) != 0) { 528 memProblemCallback(ptr, file, lineno); 529 psAbort(file, "Realloc detected a memory corruption (id %lu @ %s:%d).", 530 (unsigned long)ptr->id, ptr->file, ptr->lineno); 531 } 532 533 #ifdef PS_MEM_USE_RECYCLE 534 // Ensure the size matches that of the recycle bin 535 int bin = getRecycleBin(size); 536 if (bin < N_RECYCLE_BINS) { 537 size = recycleBinSize[bin]; // round-up size to next sized bin. 538 } 539 #endif // #ifdef PS_MEM_USE_RECYCLE 540 541 if (size == ptr->userMemorySize) { 491 unsigned int lineno, 492 const char *func) 493 { 494 if (ptr == NULL) { 495 return p_psAlloc(size, file, lineno, func); 496 } 497 498 psMemBlock *memBlock = ((psMemBlock *)ptr) - 1; 499 500 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 501 502 if (size == memBlock->userMemorySize) { 542 503 // Nothing to do 543 return vptr;504 return ptr; 544 505 } 545 506 546 507 // Reallocate the memory 547 508 548 if (safeThreads) { 549 pthread_mutex_lock(&memBlockListMutex); 550 } 551 552 bool isBlockLast = (ptr == lastMemBlockAllocated); // Is this the last block we allocated? 553 ptr = (psMemBlock *)realloc(ptr, sizeof(psMemBlock) + size + sizeof(psPtr)); 554 if (ptr == NULL) { 555 ptr = memExhaustedCallback(size); 556 if (ptr == NULL) { 557 psAbort(__func__, "Failed to reallocate %zd bytes at %s:%d", size, file, lineno); 558 } 559 } 560 561 ptr->userMemorySize = size; 562 *(psPtr *)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC; 563 509 // Is this the last block we allocated? If it is, we need to keep track of 510 // this fact and update lastMemBlockAllocated *after* the realloc or 511 // lastMemBlockAllocated will be left with a bogus value 512 bool isBlockLast = (memBlock == lastMemBlockAllocated); 513 514 memBlock = (psMemBlock *)realloc(memBlock, sizeof(psMemBlock) + size + sizeof(psPtr)); 515 if (memBlock== NULL) { 516 MUTEX_LOCK(&memBlockListMutex); 517 memBlock = memExhaustedCallback(size); 518 if (memBlock == NULL) { 519 MUTEX_UNLOCK(&memBlockListMutex); 520 psMemBlockPrint(stderr, ((psMemBlock *)ptr) - 1); 521 fprintf(stderr, "Problem reallocating block\n"); 522 PS_MEM_ABORT(__func__, "Failed to reallocate to %zd bytes at %s (%s:%d)", size, func, file, lineno); 523 } 524 } 525 526 // realloc() successed so need to update lastMemBlockAllocated if we just 527 // mucked with the last mem block 564 528 if (isBlockLast) { 565 lastMemBlockAllocated = ptr; 529 lastMemBlockAllocated = memBlock; 530 } 531 532 memBlock->userMemorySize = size; 533 *(psU32 *)((char *)(memBlock + 1) + size) = P_PS_MEMMAGIC; 534 535 MUTEX_LOCK(&memBlockListMutex); 536 537 // Is this the last block we allocated? 538 if (memBlock== lastMemBlockAllocated) { 539 lastMemBlockAllocated = memBlock; 566 540 } 567 541 568 542 // the block location may have changed, so fix the linked list addresses. 569 if (ptr->nextBlock != NULL) { 570 ptr->nextBlock->previousBlock = ptr; 571 } 572 if (ptr->previousBlock != NULL) { 573 ptr->previousBlock->nextBlock = ptr; 574 } 575 576 if (safeThreads) { 577 pthread_mutex_unlock(&memBlockListMutex); 543 if (memBlock->nextBlock != NULL) { 544 memBlock->nextBlock->previousBlock = memBlock; 545 } 546 if (memBlock->previousBlock != NULL) { 547 memBlock->previousBlock->nextBlock = memBlock; 578 548 } 579 549 580 550 // Did the user ask to be informed about this allocation? 581 if (ptr->id == p_psMemAllocID) { 582 p_psMemAllocID += memAllocCallback(ptr); 583 } 584 585 return ptr + 1; // usr memory 586 } 587 588 void p_psFree(psPtr vptr, 589 const char *filename, 590 unsigned int lineno) 591 { 592 if (vptr == NULL) { 593 return; 594 } 595 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 596 if (ptr->refCounter < 1) { 597 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 598 599 psAbort(__func__,_("Block %lu, allocated at %s:%d, freed multiple times at %s:%d."), 600 (unsigned long)ptr->id, ptr->file, ptr->lineno, filename, lineno); 601 } 602 603 if (checkMemBlock(ptr, __func__) != 0) { 604 memProblemCallback(ptr, filename, lineno); 605 psAbort(__func__,"Memory Corruption Detected."); 606 } 607 608 (void)p_psMemDecrRefCounter(vptr, filename, lineno); // this handles the free, if required. 551 if (memBlock->id == p_psMemAllocID) { 552 p_psMemAllocID += memAllocCallback(memBlock); 553 } 554 555 MUTEX_UNLOCK(&memBlockListMutex); 556 557 return memBlock + 1; // usr memory 609 558 } 610 559 … … 619 568 psS32 nleak = 0; 620 569 psS32 j = 0; 621 psMemBlock* topBlock = lastMemBlockAllocated; 622 623 if (safeThreads) { 624 pthread_mutex_lock(&memBlockListMutex); 625 } 626 627 for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) { 628 if ( (iter->refCounter > 0) && 629 ( (persistence) || (!persistence && !iter->persistent) ) && 630 (iter->id >= id0)) { 570 psMemBlock *topBlock = lastMemBlockAllocated; 571 572 MUTEX_LOCK(&memBlockListMutex); 573 574 // find the very first memblock 575 psMemBlock *memBlock = NULL; 576 for (memBlock = topBlock; memBlock->nextBlock != NULL; memBlock = memBlock->nextBlock) { } 577 578 // iterate through the block list starting with the oldest block 579 for (; memBlock != NULL; memBlock = memBlock->previousBlock) { 580 if ( (memBlock->refCounter > 0) && 581 ( (persistence) || (!persistence && !memBlock->persistent) ) && 582 (memBlock->id >= id0)) { 631 583 632 584 nleak++; … … 634 586 if (fd != NULL) { 635 587 if (nleak == 1) { 636 fprintf(fd, " %20s:line ID\n", "file");588 fprintf(fd, "# func at (file:line) ID: X\n"); 637 589 } 638 590 639 fprintf(fd, " %20s:%-4d %lu\n", iter->file, (int)iter->lineno, (unsigned long)iter->id); 591 fprintf(fd, "%s at (%s:%d) ID: %lu", memBlock->func, memBlock->file, (int)memBlock->lineno, (unsigned long)memBlock->id); 592 #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE) 593 594 size_t size = memBlock->backtraceSize; 595 char **strings = backtrace_symbols((void *const *)memBlock->backtrace, size); 596 597 fprintf(fd, " Alloc Call Depth: %zd\n", size); 598 599 for (int i = 0; i < size; i++) { 600 // always ident 601 int ident = 4; // initial indent 602 ident += 2 * i; // nesting depth 603 fprintf(fd, "%*s", ident, ""); 604 605 // if the caller was an anon function then strchr won't 606 // find a '(' in the string and will return NULL 607 char *caller = caller = strchr(strings[i], '('); 608 if (caller) { 609 // skip over the '(' 610 caller++; 611 // find the end of the symbol name 612 size_t callerLength = abs(strchr(caller, '+') - caller); 613 // print just the symbol name 614 for (int i = 0; i < callerLength; i++) { 615 fputc(caller[i],fd); 616 } 617 fprintf(fd, "\n"); 618 } else { 619 fprintf(fd, "(unknown)\n"); 620 } 621 } 622 623 free (strings); 624 #else // ifdef HAVE_BACKTRACE 625 // \n after "Memory Block ID" 626 fprintf(fd, "\n"); 627 #endif // ifdef HAVE_BACKTRACE 628 640 629 } 641 630 } 642 631 } 643 632 644 if (safeThreads) { 645 pthread_mutex_unlock(&memBlockListMutex); 646 } 633 MUTEX_UNLOCK(&memBlockListMutex); 647 634 648 635 if (nleak == 0 || array == NULL) { … … 650 637 } 651 638 652 *array = p_psAlloc(nleak * sizeof(psMemBlock), __FILE__, __LINE__); 653 if (safeThreads) { 654 pthread_mutex_lock(&memBlockListMutex); 655 } 656 657 for (psMemBlock* iter = topBlock; iter != NULL; iter = iter->nextBlock) { 658 if ( (iter->refCounter > 0) && 659 ( (persistence) || (!persistence && !iter->persistent) ) && 660 (iter->id >= id0)) { 661 662 (*array)[j++] = iter; 639 *array = psAlloc(nleak * sizeof(psMemBlock)); 640 641 MUTEX_LOCK(&memBlockListMutex); 642 643 for (psMemBlock *memBlock = topBlock; memBlock != NULL; memBlock = memBlock ->nextBlock) { 644 if ( (memBlock->refCounter > 0) && 645 ( (persistence) || (!persistence && !memBlock->persistent) ) && 646 (memBlock->id >= id0)) { 647 648 (*array)[j++] = memBlock; 663 649 if (j == nleak) { // found them all 664 650 break; … … 667 653 } 668 654 669 if (safeThreads) { 670 pthread_mutex_unlock(&memBlockListMutex); 671 } 655 MUTEX_UNLOCK(&memBlockListMutex); 672 656 673 657 return nleak; … … 679 663 680 664 // return refCounter 681 psReferenceCount p sMemGetRefCounter(const psPtr ptr)682 { 683 psMemBlock* ptr2;684 psU32 refCount;685 665 psReferenceCount p_psMemGetRefCounter(const psPtr ptr, 666 const char *file, 667 unsigned int lineno, 668 const char *func) 669 { 686 670 if (ptr == NULL) { 687 671 return 0; 688 672 } 689 673 690 ptr2 = ((psMemBlock* ) ptr) - 1; 691 692 if (checkMemBlock(ptr2, __func__) != 0) { 693 memProblemCallback(ptr2, __func__, __LINE__); 694 } 695 696 if (safeThreads) { 697 pthread_mutex_lock(&ptr2->refCounterMutex); 698 } 699 refCount = ptr2->refCounter; 700 if (safeThreads) { 701 pthread_mutex_unlock(&ptr2->refCounterMutex); 702 } 703 704 return refCount; 674 psMemBlock *memBlock = ((psMemBlock *) ptr) - 1; 675 676 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 677 678 return memBlock->refCounter; 705 679 } 706 680 707 681 // increment and return refCounter 708 psPtr p_psMemIncrRefCounter(const psPtr vptr,682 psPtr p_psMemIncrRefCounter(const psPtr ptr, 709 683 const char *file, 710 psS32 lineno) 711 { 712 psMemBlock* ptr; 713 714 if (vptr == NULL) { 715 return vptr; 716 } 717 718 ptr = ((psMemBlock* ) vptr) - 1; 719 720 if (checkMemBlock(ptr, __func__)) { 721 memProblemCallback(ptr, file, lineno); 722 } 723 724 if (safeThreads) { 725 pthread_mutex_lock(&ptr->refCounterMutex); 726 } 727 ptr->refCounter++; 728 if (safeThreads) { 729 pthread_mutex_unlock(&ptr->refCounterMutex); 730 } 684 unsigned int lineno, 685 const char *func) 686 { 687 if (ptr == NULL) { 688 return ptr; 689 } 690 691 psMemBlock* memBlock = ((psMemBlock *) ptr) - 1; 692 693 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 694 695 memBlock->refCounter++; 731 696 732 697 // Did the user ask to be informed about this allocation? 733 if (ptr->id == p_psMemAllocID) { 734 p_psMemAllocID += memAllocCallback(ptr); 735 } 736 737 return vptr; 738 } 739 698 MUTEX_LOCK(&memBlockListMutex); 699 if (memBlock->id == p_psMemAllocID) { 700 p_psMemAllocID += memAllocCallback(memBlock); 701 } 702 MUTEX_UNLOCK(&memBlockListMutex); 703 704 return ptr; 705 } 706 707 #if 0 740 708 psPtr p_psMemSetRefCounter(psPtr vptr, 741 709 psReferenceCount count, … … 755 723 ptr = ((psMemBlock* ) vptr) - 1; 756 724 757 if (checkMemBlock(ptr, __func__)) { 725 if (isBadMemBlock(ptr, __func__)) { 726 (void)p_psMemDecrRefCounter(vptr, filename, lineno); 758 727 memProblemCallback(ptr, file, lineno); 759 728 } 760 729 761 if (safeThreads) {762 pthread_mutex_lock(&ptr->refCounterMutex);763 }764 730 ptr->refCounter = count; 765 if (safeThreads) {766 pthread_mutex_unlock(&ptr->refCounterMutex);767 }768 731 769 732 if (count < 1) { … … 773 736 return vptr; 774 737 } 738 #endif 775 739 776 740 // decrement and return refCounter 777 psPtr p_psMemDecrRefCounter(psPtr vptr,741 psPtr p_psMemDecrRefCounter(psPtr ptr, 778 742 const char *file, 779 psS32 lineno) 780 { 781 if (vptr == NULL) { 743 unsigned int lineno, 744 const char *func) 745 { 746 if (ptr == NULL) { 782 747 return NULL; 783 748 } 784 749 785 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 786 787 if (checkMemBlock(ptr, __func__) != 0) { 788 memProblemCallback(ptr, file, lineno); 789 return NULL; 790 } 750 psMemBlock *memBlock = ((psMemBlock *) ptr) - 1; 751 752 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 753 754 // if we have multiple references, just decrement the count and return. 755 if (memBlock->refCounter > 1) { 756 memBlock->refCounter--; 757 758 // Did the user ask to be informed about this deallocation? 759 MUTEX_LOCK(&memBlockListMutex); 760 if (memBlock->id == p_psMemFreeID) { 761 p_psMemFreeID += memFreeCallback(memBlock); 762 } 763 MUTEX_UNLOCK(&memBlockListMutex); 764 765 return ptr; 766 } 767 768 // we can't invoke freeFunc() while we're holding memBlockListMutex as it 769 // may invoke psFree() itself 770 if (memBlock->freeFunc != NULL) { 771 memBlock->freeFunc(ptr); 772 } 773 774 MUTEX_LOCK(&memBlockListMutex); 791 775 792 776 // Did the user ask to be informed about this deallocation? 793 if ( ptr->id == p_psMemFreeID) {777 if (memBlock->id == p_psMemFreeID) { 794 778 p_psMemFreeID += memFreeCallback(ptr); 795 779 } 796 780 797 if (safeThreads) { 798 pthread_mutex_lock(&ptr->refCounterMutex); 799 } 800 801 if (ptr->refCounter > 1) { 802 ptr->refCounter--; // multiple references, just decrement the count. 803 if (safeThreads) { 804 pthread_mutex_unlock(&ptr->refCounterMutex); 805 } 806 807 } else { 808 if (safeThreads) { 809 pthread_mutex_unlock(&ptr->refCounterMutex); 810 } 811 812 if (ptr->freeFunc != NULL) { 813 ptr->freeFunc(vptr); 814 } 815 816 if (safeThreads) { 817 pthread_mutex_lock(&memBlockListMutex); 818 } 819 820 // cut the memBlock out of the memBlock list 821 if (ptr->nextBlock != NULL) { 822 ptr->nextBlock->previousBlock = ptr->previousBlock; 823 } 824 if (ptr->previousBlock != NULL) { 825 ptr->previousBlock->nextBlock = ptr->nextBlock; 826 } 827 if (lastMemBlockAllocated == ptr) { 828 lastMemBlockAllocated = ptr->nextBlock; 829 } 830 831 if (safeThreads) { 832 pthread_mutex_unlock(&memBlockListMutex); 833 } 834 835 #ifdef PS_MEM_USE_RECYCLE 836 // do we recycle? 837 int bin = getRecycleBin(ptr->userMemorySize); 838 if (bin < N_RECYCLE_BINS && recycleBinNums[bin] < MAX_RECYCLE) { 839 ptr->refCounter = 0; 840 recyclePush(ptr, bin); 841 } else 842 #endif // #ifdef PS_MEM_USE_RECYCLE 843 { 844 // memory is larger than I want to recycle. 845 #ifdef PS_MEM_DEBUG 846 (void)p_psRealloc(vptr, 0, file, lineno); 847 ptr->previousBlock = NULL; 848 ptr->nextBlock = deadBlockList; 849 if (deadBlockList != NULL) { 850 deadBlockList->previous = ptr; 851 } 852 deadBlockList = ptr; 853 #else // #ifdef PS_MEM_DEBUG 854 855 if (safeThreads) { 856 pthread_mutex_destroy(&ptr->refCounterMutex); 857 } 858 free(ptr); 859 #endif // #else - #ifdef PS_MEM_DEBUG 860 861 } 862 863 vptr = NULL; // since we freed it, make sure we return NULL. 864 } 865 866 return vptr; 867 } 868 869 void psMemSetDeallocator(psPtr ptr, 870 psFreeFunc freeFunc) 781 // cut the memBlock out of the memBlock list 782 if (memBlock->nextBlock != NULL) { 783 memBlock->nextBlock->previousBlock = memBlock->previousBlock; 784 } 785 if (memBlock->previousBlock != NULL) { 786 memBlock->previousBlock->nextBlock = memBlock->nextBlock; 787 } 788 if (lastMemBlockAllocated == memBlock) { 789 lastMemBlockAllocated = memBlock->nextBlock; 790 } 791 792 MUTEX_UNLOCK(&memBlockListMutex); 793 794 // invoke free only after we've released the block list lock as free() 795 // could take awhile. We can get away with this as at this point the 796 // memBlock is no longer part of the mem block list. 797 #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE) 798 799 free(memBlock->backtrace); 800 #endif 801 802 free(memBlock); 803 804 // since we freed it, make sure we return NULL. 805 return NULL; 806 } 807 808 void p_psMemSetDeallocator(psPtr ptr, 809 psFreeFunc freeFunc, 810 const char *file, 811 unsigned int lineno, 812 const char *func) 871 813 { 872 814 if (ptr == NULL) { … … 874 816 } 875 817 876 psMemBlock* PTR = ((psMemBlock* )ptr) - 1;877 878 if (checkMemBlock(PTR, __func__) != 0) {879 memProblemCallback(PTR, __func__, __LINE__); 880 }881 882 PTR->freeFunc = freeFunc; 883 884 } 885 886 psFreeFunc psMemGetDeallocator(const psPtr ptr)818 psMemBlock* memBlock = ((psMemBlock *)ptr) - 1; 819 820 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 821 822 memBlock->freeFunc = freeFunc; 823 } 824 825 psFreeFunc p_psMemGetDeallocator(const psPtr ptr, 826 const char *file, 827 unsigned int lineno, 828 const char *func) 887 829 { 888 830 if (ptr == NULL) { … … 890 832 } 891 833 892 psMemBlock* PTR = ((psMemBlock* ) ptr) - 1; 893 894 if (checkMemBlock(PTR, __func__) != 0) { 895 memProblemCallback(PTR, __func__, __LINE__); 896 } 897 898 return PTR->freeFunc; 899 } 900 901 bool psMemCheckType(psDataType type, 902 psPtr ptr) 903 { 904 PS_ASSERT_PTR(ptr, false); 905 906 switch(type) { 907 case PS_DATA_ARRAY: 908 if ( psMemCheckArray(ptr) ) 909 return true; 910 else { 911 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 912 "Incorrect pointer. Datatypes do not match.\n"); 913 break; 914 } 915 case PS_DATA_BITSET: 916 if ( psMemCheckBitSet(ptr) ) 917 return true; 918 else { 919 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 920 "Incorrect pointer. Datatypes do not match.\n"); 921 break; 922 } 923 case PS_DATA_CUBE: 924 if ( psMemCheckCube(ptr) ) 925 return true; 926 else { 927 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 928 "Incorrect pointer. Datatypes do not match.\n"); 929 break; 930 } 931 case PS_DATA_FITS: 932 if ( psMemCheckFits(ptr) ) 933 return true; 934 else { 935 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 936 "Incorrect pointer. Datatypes do not match.\n"); 937 break; 938 } 939 case PS_DATA_HASH: 940 if ( psMemCheckHash(ptr) ) 941 return true; 942 else { 943 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 944 "Incorrect pointer. Datatypes do not match.\n"); 945 break; 946 } 947 case PS_DATA_HISTOGRAM: 948 if ( psMemCheckHistogram(ptr) ) 949 return true; 950 else { 951 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 952 "Incorrect pointer. Datatypes do not match.\n"); 953 break; 954 } 955 case PS_DATA_IMAGE: 956 if ( psMemCheckImage(ptr) ) 957 return true; 958 else { 959 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 960 "Incorrect pointer. Datatypes do not match.\n"); 961 break; 962 } 963 case PS_DATA_KERNEL: 964 if ( psMemCheckKernel(ptr) ) 965 return true; 966 else { 967 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 968 "Incorrect pointer. Datatypes do not match.\n"); 969 break; 970 } 971 case PS_DATA_LINE: 972 if ( psMemCheckLine(ptr) ) 973 return true; 974 else { 975 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 976 "Incorrect pointer. Datatypes do not match.\n"); 977 break; 978 } 979 case PS_DATA_LIST: 980 if ( psMemCheckList(ptr) ) 981 return true; 982 else { 983 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 984 "Incorrect pointer. Datatypes do not match.\n"); 985 break; 986 } 987 case PS_DATA_LOOKUPTABLE: 988 if ( psMemCheckLookupTable(ptr) ) 989 return true; 990 else { 991 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 992 "Incorrect pointer. Datatypes do not match.\n"); 993 break; 994 } 995 case PS_DATA_METADATA: 996 if ( psMemCheckMetadata(ptr) ) 997 return true; 998 else { 999 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1000 "Incorrect pointer. Datatypes do not match.\n"); 1001 break; 1002 } 1003 case PS_DATA_METADATAITEM: 1004 if ( psMemCheckMetadataItem(ptr) ) 1005 return true; 1006 else { 1007 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1008 "Incorrect pointer. Datatypes do not match.\n"); 1009 break; 1010 } 1011 case PS_DATA_MINIMIZATION: 1012 if ( psMemCheckMinimization(ptr) ) 1013 return true; 1014 else { 1015 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1016 "Incorrect pointer. Datatypes do not match.\n"); 1017 break; 1018 } 1019 case PS_DATA_PIXELS: 1020 if ( psMemCheckPixels(ptr) ) 1021 return true; 1022 else { 1023 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1024 "Incorrect pointer. Datatypes do not match.\n"); 1025 break; 1026 } 1027 case PS_DATA_PLANE: 1028 if ( psMemCheckPlane(ptr) ) 1029 return true; 1030 else { 1031 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1032 "Incorrect pointer. Datatypes do not match.\n"); 1033 break; 1034 } 1035 case PS_DATA_PLANEDISTORT: 1036 if ( psMemCheckPlaneDistort(ptr) ) 1037 return true; 1038 else { 1039 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1040 "Incorrect pointer. Datatypes do not match.\n"); 1041 break; 1042 } 1043 case PS_DATA_PLANETRANSFORM: 1044 if ( psMemCheckPlaneTransform(ptr) ) 1045 return true; 1046 else { 1047 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1048 "Incorrect pointer. Datatypes do not match.\n"); 1049 break; 1050 } 1051 case PS_DATA_POLYNOMIAL1D: 1052 if ( psMemCheckPolynomial1D(ptr) ) 1053 return true; 1054 else { 1055 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1056 "Incorrect pointer. Datatypes do not match.\n"); 1057 break; 1058 } 1059 case PS_DATA_POLYNOMIAL2D: 1060 if ( psMemCheckPolynomial2D(ptr) ) 1061 return true; 1062 else { 1063 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1064 "Incorrect pointer. Datatypes do not match.\n"); 1065 break; 1066 } 1067 case PS_DATA_POLYNOMIAL3D: 1068 if ( psMemCheckPolynomial3D(ptr) ) 1069 return true; 1070 else { 1071 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1072 "Incorrect pointer. Datatypes do not match.\n"); 1073 break; 1074 } 1075 case PS_DATA_POLYNOMIAL4D: 1076 if ( psMemCheckPolynomial4D(ptr) ) 1077 return true; 1078 else { 1079 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1080 "Incorrect pointer. Datatypes do not match.\n"); 1081 break; 1082 } 1083 case PS_DATA_PROJECTION: 1084 if ( psMemCheckProjection(ptr) ) 1085 return true; 1086 else { 1087 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1088 "Incorrect pointer. Datatypes do not match.\n"); 1089 break; 1090 } 1091 case PS_DATA_REGION: 1092 if ( psMemCheckRegion(ptr) ) 1093 return true; 1094 else { 1095 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1096 "Incorrect pointer. Datatypes do not match.\n"); 1097 break; 1098 } 1099 case PS_DATA_SCALAR: 1100 if ( psMemCheckScalar(ptr) ) 1101 return true; 1102 else { 1103 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1104 "Incorrect pointer. Datatypes do not match.\n"); 1105 break; 1106 } 1107 case PS_DATA_SPHERE: 1108 if ( psMemCheckSphere(ptr) ) 1109 return true; 1110 else { 1111 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1112 "Incorrect pointer. Datatypes do not match.\n"); 1113 break; 1114 } 1115 case PS_DATA_SPHEREROT: 1116 if ( psMemCheckSphereRot(ptr) ) 1117 return true; 1118 else { 1119 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1120 "Incorrect pointer. Datatypes do not match.\n"); 1121 break; 1122 } 1123 case PS_DATA_SPLINE1D: 1124 if ( psMemCheckSpline1D(ptr) ) 1125 return true; 1126 else { 1127 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1128 "Incorrect pointer. Datatypes do not match.\n"); 1129 break; 1130 } 1131 case PS_DATA_STATS: 1132 if ( psMemCheckStats(ptr) ) 1133 return true; 1134 else { 1135 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1136 "Incorrect pointer. Datatypes do not match.\n"); 1137 break; 1138 } 1139 case PS_DATA_STRING: 1140 if ( psMemCheckString(ptr) ) 1141 return true; 1142 else { 1143 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1144 "Incorrect pointer. Datatypes do not match.\n"); 1145 break; 1146 } 1147 case PS_DATA_TIME: 1148 if ( psMemCheckTime(ptr) ) 1149 return true; 1150 else { 1151 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1152 "Incorrect pointer. Datatypes do not match.\n"); 1153 break; 1154 } 1155 case PS_DATA_VECTOR: 1156 if ( psMemCheckVector(ptr) ) 1157 return true; 1158 else { 1159 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 1160 "Incorrect pointer. Datatypes do not match.\n"); 1161 break; 1162 } 1163 default: 1164 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 1165 "Invalid datatype specified.\n"); 1166 } 1167 return false; 834 psMemBlock* memBlock = ((psMemBlock *)ptr) - 1; 835 836 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 837 838 return memBlock->freeFunc; 1168 839 } 1169 840 1170 841 bool psMemSetThreadSafety(bool safe) 1171 842 { 1172 bool out = safeThreads; 843 MUTEX_LOCK(&memBlockListMutex); 844 845 bool oldState = safeThreads; 1173 846 safeThreads = safe; 1174 return out; 847 848 MUTEX_UNLOCK(&memBlockListMutex); 849 850 return oldState; 1175 851 } 1176 852 1177 853 bool psMemGetThreadSafety(void) 1178 854 { 1179 return safeThreads; 1180 } 1181 1182 bool p_psMemGetPersistent(psPtr vptr) 1183 { 1184 if (vptr == NULL) { 855 MUTEX_LOCK(&memBlockListMutex); 856 857 bool oldState = safeThreads; 858 859 MUTEX_UNLOCK(&memBlockListMutex); 860 861 return oldState; 862 } 863 864 bool p_psMemGetPersistent(psPtr ptr, 865 const char *file, 866 unsigned int lineno, 867 const char *func) 868 { 869 if (ptr == NULL) { 1185 870 return NULL; 1186 871 } 1187 872 1188 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 1189 1190 if (checkMemBlock(ptr, __func__) != 0) { 1191 memProblemCallback(ptr, __func__, __LINE__); 1192 } 1193 1194 return ptr->persistent; 1195 } 1196 1197 void p_psMemSetPersistent(psPtr vptr, 1198 bool value) 1199 { 1200 if (vptr == NULL) { 873 psMemBlock* memBlock = ((psMemBlock *) ptr) - 1; 874 875 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 876 877 return memBlock->persistent; 878 } 879 880 void p_psMemSetPersistent(psPtr ptr, 881 bool value, 882 const char *file, 883 unsigned int lineno, 884 const char *func) 885 { 886 if (ptr == NULL) { 1201 887 return; 1202 888 } 1203 889 1204 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 1205 1206 if (checkMemBlock(ptr, __func__) != 0) { 1207 memProblemCallback(ptr, __func__, __LINE__); 1208 } 1209 1210 ptr->persistent = value; 890 psMemBlock* memBlock = ((psMemBlock *) ptr) - 1; 891 892 HANDLE_BAD_BLOCK(memBlock, file, lineno, func); 893 894 memBlock->persistent = value; 1211 895 } 1212 896 … … 1221 905 size_t psMemStats(const bool print, // print details as they're found? 1222 906 size_t *allocated, // memory that's currently allocated (but not persistent) 1223 size_t *persistent, // persistent memory that's currently allocated 1224 size_t *freelist) // memory that's waiting to be recycled 907 size_t *persistent) // persistent memory that's currently allocated 1225 908 { 1226 909 const size_t overhead = sizeof(psMemBlock) + sizeof(psPtr); // overhead on each allocation … … 1230 913 } 1231 914 1232 if (safeThreads) { 1233 pthread_mutex_lock(&memBlockListMutex); 1234 } 915 MUTEX_LOCK(&memBlockListMutex); 1235 916 /* 1236 917 * All memory that's currently allocated, whether persistent or not … … 1264 945 printf("Persistent %6s %10zd %8zd\n", "", persist, npersist); 1265 946 } 1266 /* 1267 * Count the memory on the free list 1268 */ 1269 size_t freelist_s; 1270 if (freelist == NULL) { 1271 freelist = &freelist_s; 1272 } 1273 1274 *freelist = 0; 1275 int nblock_tot = 0; 1276 #ifdef PS_MEM_USE_RECYCLE 1277 1278 for (int i = 0; recycleBinSize[i] < P_PS_LARGE_BLOCK_SIZE; i++) { 1279 size_t bin_contents = 0; 1280 size_t nblock = 0; 1281 for (const psMemBlock *ptr = recycleMemBlockList[i]; ptr != NULL; ptr = ptr->nextBlock) { 1282 nblock++; 1283 bin_contents += ptr->userMemorySize + overhead; 1284 } 1285 *freelist += bin_contents; 1286 nblock_tot += nblock; 1287 1288 if (print) { 1289 printf("Freelist %6d %10d %8d\n", recycleBinSize[i], bin_contents, nblock); 1290 } 1291 } 1292 #endif // #ifdef PS_MEM_USE_RECYCLE 1293 1294 if (print) { 1295 printf("Freelist %6s %10zd %8d\n", "", *freelist, nblock_tot); 1296 } 1297 1298 1299 if (safeThreads) { 1300 pthread_mutex_unlock(&memBlockListMutex); 1301 } 1302 1303 return *freelist + *allocated + *persistent; 1304 } 947 948 MUTEX_UNLOCK(&memBlockListMutex); 949 950 return *allocated + *persistent; 951 } 952 953 int psMemBlockPrint(FILE *output, const psMemBlock *memBlock) 954 { 955 return fprintf(output, 956 "Memory Block ID: %lu @ %p\n" 957 "\tPrevious Block: %p Next Block: %p\n" 958 "\tFree function: %p\n" 959 "\tSize: %zd Reference count: %lu Persistent: %s\n" 960 "\tPosts: %x %x %x\n" 961 "\tAllocated in %s at (%s:%d)\n" 962 "\t\tby Thread ID %lu\n", 963 memBlock->id, memBlock, 964 memBlock->previousBlock, memBlock->nextBlock, 965 memBlock->freeFunc, 966 memBlock->userMemorySize, memBlock->refCounter, (memBlock->persistent ? "Yes" : "No"), 967 memBlock->startblock, memBlock->endblock, 968 *(psU32 *)((char *) (memBlock + 1) + memBlock->userMemorySize), 969 memBlock->func, memBlock->file, memBlock->lineno, memBlock->tid); 970 } -
trunk/psLib/src/sys/psMemory.h
r11258 r11265 2 2 * @brief Contains the definitions for the memory management system 3 3 * 4 * This is the generic memory management system put inbetween the user's high level code and the OS-level 5 * memory allocation routines. This system adds such features as callback routines for memory error events, 6 * tracing capabilities, and reference counting. 7 * 8 * @author Robert Lupton, Princeton University 9 * @author Robert DeSonia, MHPCC 10 * 11 * $Revision: 1.63 $ $Name: not supported by cvs2svn $ 12 * $Date: 2007-01-24 20:04:00 $ 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 4 * @brief Contains the definitions for the memory management system 5 * 6 * This is the generic memory management system put inbetween the user's high 7 * level code and the OS-level memory allocation routines. This system adds 8 * such features as callback routines for memory error events, tracing 9 * capabilities, and reference counting. 10 * 11 * @author Robert DeSonia, MHPCC 12 * @author Robert Lupton, Princeton University 13 * @author Joshua Hoblitt, University of Hawaii 14 * 15 * @ingroup MemoryManagement 16 * 17 * @version $Revision: 1.64 $ $Name: not supported by cvs2svn $ 18 * @date $Date: 2007-01-24 22:14:48 $ 19 * 20 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 14 21 */ 15 22 … … 24 31 #include "psType.h" 25 32 26 #define P_PS_MEMMAGIC (psPtr)0xdeadbeef // Magic number in psMemBlock header 33 /** @addtogroup MemoryManagement 34 * @{ 35 */ 36 37 #define P_PS_MEMMAGIC (psU32)0xdeadbeef // Magic number in psMemBlock header 27 38 28 39 /// typedef for memory identification numbers. Guaranteed to be some variety of integer. … … 40 51 * aligned for all storage types. 41 52 */ 53 54 // The memory overhead of a psMemBlock + the trailing post can be checked in 55 // gdb with the following command: 56 // p sizeof(psMemBlock) + sizeof(void*) 42 57 typedef struct psMemBlock 43 58 { 44 const void*startblock; ///< initialised to p_psMEMMAGIC59 const psU32 startblock; ///< initialised to p_psMEMMAGIC 45 60 struct psMemBlock* previousBlock; ///< previous block in allocation list 46 61 struct psMemBlock* nextBlock; ///< next block allocation list … … 48 63 size_t userMemorySize; ///< the size of the user-portion of the memory block 49 64 const psMemId id; ///< a unique ID for this allocation 65 const pthread_t tid; ///< set from pthread_self(); 50 66 const char *file; ///< set from __FILE__ in e.g. p_psAlloc 51 67 const unsigned int lineno; ///< set from __LINE__ in e.g. p_psAlloc 52 pthread_mutex_t refCounterMutex; ///< mutex to ensure exclusive access to reference counter 68 const char *func; ///< set from __func__ 69 #ifdef HAVE_BACKTRACE 70 71 const void **backtrace; ///< set from backtrace() 72 const size_t backtraceSize; ///< set from bracktrace() 73 #endif // ifdef HAVE_BACKTRACE 74 53 75 psReferenceCount refCounter; ///< how many times pointer is referenced 54 76 bool persistent; ///< marks if this non-user persistent data like error stack, etc. 55 const void*endblock; ///< initialised to p_psMEMMAGIC77 const psU32 endblock; ///< initialised to p_psMEMMAGIC 56 78 } 57 79 psMemBlock; … … 81 103 typedef void (*psMemProblemCallback) ( 82 104 psMemBlock* ptr, ///< the pointer to the problematic memory block. 83 const char *file name,///< the file in which the problem originated105 const char *file, ///< the file in which the problem originated 84 106 unsigned int lineno ///< the line number in which the problem originated 85 107 ); … … 108 130 109 131 #else // #ifdef DOXYGEN 132 133 #ifdef __GNUC__ 110 134 psPtr p_psAlloc( 111 135 size_t size, ///< Size required 112 const char *filename, ///< File of call 113 unsigned int lineno ///< Line number of call 114 ); 136 const char *file, ///< File of caller 137 unsigned int lineno, ///< Line number of caller 138 const char *func ///< Function name of caller 139 ) __attribute__((malloc)); 140 # else // __GNUC__ 141 142 psPtr p_psAlloc( 143 size_t size, ///< Size required 144 const char *file, ///< File of caller 145 unsigned int lineno, ///< Line number of caller 146 const char *func ///< Function name of caller 147 ); 148 #endif // __GNUC__ 115 149 116 150 /// Memory allocation. psAlloc sends file and line number to p_psAlloc. 117 151 #ifndef SWIG 118 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__) 152 #define psAlloc(size) \ 153 p_psAlloc(size, __FILE__, __LINE__, __func__) 119 154 #endif // ! SWIG 120 155 121 156 #endif // ! DOXYGEN 157 122 158 123 159 /** Set the deallocator routine … … 128 164 * 129 165 */ 166 #ifdef DOXYGEN 167 130 168 void psMemSetDeallocator( 131 169 psPtr ptr, ///< the memory block to operate on 132 170 psFreeFunc freeFunc ///< the function to be executed at deallocation 133 171 ); 172 173 #else // ifdef DOXYGEN 174 175 void p_psMemSetDeallocator( 176 psPtr ptr, ///< the memory block to operate on 177 psFreeFunc freeFunc, ///< the function to be executed at deallocation 178 const char *file, ///< File of caller 179 unsigned int lineno, ///< Line number of caller 180 const char *func ///< Function name of caller 181 ); 182 183 #ifndef SWIG 184 #define psMemSetDeallocator(ptr, freeFunc) \ 185 p_psMemSetDeallocator(ptr, freeFunc, __FILE__, __LINE__, __func__); 186 #endif // ! SWIG 187 188 #endif // ifdef DOXYGEN 189 134 190 135 191 /** Get the deallocator routine … … 142 198 * @return psFreeFunc the routine to be called at deallocation. 143 199 */ 200 #ifdef DOXYGEN 201 144 202 psFreeFunc psMemGetDeallocator( 145 const psPtr ptr ///< the memory block 146 ); 147 148 /** Checks the deallocator to see if the pointer matches the desired datatype. 149 * 150 * @return bool: True if type matches, otherwise false. 151 */ 152 bool psMemCheckType( 153 psDataType type, ///< The desired psDataType to match 154 psPtr ptr ///< The desired pointer to match 155 ); 203 const psPtr ptr ///< the memory block 204 ); 205 206 #else // ifdef DOXYGEN 207 208 psFreeFunc p_psMemGetDeallocator( 209 const psPtr ptr, ///< the memory block 210 const char *file, ///< File of caller 211 unsigned int lineno, ///< Line number of caller 212 const char *func ///< Function name of caller 213 ); 214 215 #ifndef SWIG 216 #define psMemGetDeallocator(ptr) \ 217 p_psMemGetDeallocator(ptr, __FILE__, __LINE__, __func__) 218 #endif // ! SWIG 219 220 #endif // ifdef DOXYGEN 221 156 222 157 223 /** Activate or Deactivate thread safety and mutex locking in the memory management. … … 176 242 bool psMemGetThreadSafety(void); 177 243 244 178 245 /** Set the memory as persistent so that it is ignored when detecting memory leaks. 179 246 * … … 186 253 * 187 254 */ 255 #ifdef DOXYGEN 256 257 void psMemSetPersistent( 258 psPtr ptr, ///< the memory block to operate on 259 bool value, ///< true if memory is persistent, otherwise false 260 ); 261 262 #else // #ifdef DOXYGEN 263 188 264 void p_psMemSetPersistent( 189 265 psPtr ptr, ///< the memory block to operate on 190 bool value ///< true if memory is persistent, otherwise false 191 ); 266 bool value, ///< true if memory is persistent, otherwise false 267 const char *file, ///< File of caller 268 unsigned int lineno, ///< Line number of caller 269 const char *func ///< Function name of caller 270 ); 271 272 #ifndef SWIG 273 #define psMemSetPersistent(ptr, value) \ 274 p_psMemSetPersistent(ptr, value, __FILE__, __LINE__, __func__); 275 #endif // ! SWIG 276 277 #endif // DOXYGEN 278 192 279 193 280 /** Set whether allocated memory is persistent … … 198 285 */ 199 286 bool p_psMemAllocatePersistent(bool is_persistent); ///< Should all memory allocated be persistent? 287 200 288 201 289 /** Get the memory's persistent flag. … … 208 296 * @return bool true if memory is marked persistent, otherwise false. 209 297 */ 298 #ifdef DOXYGEN 299 300 bool psMemGetPersistent( 301 psPtr ptr, ///< the memory block to check. 302 ); 303 #else // ifdef DOXYGEN 304 210 305 bool p_psMemGetPersistent( 211 psPtr ptr ///< the memory block to check. 212 ); 306 psPtr ptr, ///< the memory block to check. 307 const char *file, ///< File of caller 308 unsigned int lineno, ///< Line number of caller 309 const char *func ///< Function name of caller 310 ); 311 312 #ifndef SWIG 313 #define psMemGetPersistent(ptr) \ 314 p_MemGetPersistent(ptr, __FILE__, __LINE__, __func__); 315 #endif // ! SWIG 316 317 #endif // DOXYGEN 213 318 214 319 … … 226 331 #else // #ifdef DOXYGEN 227 332 333 #ifdef __GNUC__ 228 334 psPtr p_psRealloc( 229 335 psPtr ptr, ///< Pointer to re-allocate 230 336 size_t size, ///< Size required 231 const char *filename, ///< File of call 232 unsigned int lineno ///< Line number of call 233 ); 337 const char *file, ///< File of caller 338 unsigned int lineno, ///< Line number of caller 339 const char *func ///< Function name of caller 340 ) __attribute__((malloc)); 341 # else // __GNUC__ 342 343 psPtr p_psRealloc( 344 psPtr ptr, ///< Pointer to re-allocate 345 size_t size, ///< Size required 346 const char *file, ///< File of caller 347 unsigned int lineno, ///< Line number of caller 348 const char *func ///< Function name of caller 349 ); 350 #endif // __GNUC__ 234 351 235 352 /// Memory re-allocation. psRealloc sends file and line number to p_psRealloc. 236 353 #ifndef SWIG 237 #define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__) 354 #define psRealloc(ptr, size) \ 355 p_psRealloc(ptr, size, __FILE__, __LINE__, __func__) 238 356 #endif // ! SWIG 239 357 240 358 #endif // ! DOXYGEN 359 241 360 242 361 /** Free memory. This operates much like free(). … … 249 368 ); 250 369 #else // #ifdef DOXYGEN 251 void p_psFree(252 psPtr ptr, ///< Pointer to free253 const char *filename, ///< File of call254 unsigned int lineno ///< Line number of call255 );256 370 257 371 /// Free memory. psFree sends file and line number to p_psFree. 258 372 #ifndef SWIG 259 //#define psFree(ptr) { p_psFree((psPtr)ptr, __FILE__, __LINE__); *(void**)&(ptr) = NULL; } 260 #define psFree(ptr) { p_psFree((psPtr)ptr, __FILE__, __LINE__); } 373 #define psFree(ptr) \ 374 p_psMemDecrRefCounter((psPtr *)ptr, __FILE__, __LINE__, __func__); 261 375 #endif // ! SWIG 262 376 263 377 #endif // ! DOXYGEN 378 264 379 265 380 /** Check for memory leaks. This scans for allocated memory buffers not freed with an ID not less than id0. … … 290 405 */ 291 406 int psMemCheckCorruption( 292 bool abort_on_error ///< Abort on detecting corruption? 407 FILE *output, ///< FILE to write corrupted blocks too 408 bool abort_on_error ///< Abort on detecting corruption? 293 409 ); 294 410 … … 298 414 * 299 415 */ 416 #ifdef DOXYGEN 417 300 418 psReferenceCount psMemGetRefCounter( 301 419 const psPtr ptr ///< Pointer to get refCounter for 302 420 ); 303 421 422 #else // ifdef DOXYGEN 423 424 psReferenceCount p_psMemGetRefCounter( 425 const psPtr ptr, ///< Pointer to get refCounter for 426 const char *file, ///< File of call 427 unsigned int lineno, ///< Line number of call 428 const char *func ///< Function name of caller 429 ); 430 431 #ifndef SWIG 432 #define psMemGetRefCounter(ptr) \ 433 p_psMemGetRefCounter(ptr, __FILE__, __LINE__, __func__) 434 #endif // !SWIG 435 436 #endif // !DOXYGEN 437 438 304 439 /** Increment reference counter and return the pointer 305 440 * … … 308 443 */ 309 444 #ifdef DOXYGEN 445 310 446 psPtr psMemIncrRefCounter( 311 447 const psPtr ptr ///< Pointer to increment refCounter, and return 312 448 ); 313 #else 449 #else // ifdef DOXYGEN 450 314 451 psPtr p_psMemIncrRefCounter( 315 const psPtr vptr, ///< Pointer to increment refCounter, and return452 const psPtr ptr, ///< Pointer to increment refCounter, and return 316 453 const char *file, ///< File of call 317 psS32 lineno ///< Line number of call 318 ); 319 320 #ifndef SWIG 321 #define psMemIncrRefCounter(vptr) p_psMemIncrRefCounter(vptr, __FILE__, __LINE__) 454 unsigned int lineno, ///< Line number of call 455 const char *func ///< Function name of caller 456 ); 457 458 #ifndef SWIG 459 #define psMemIncrRefCounter(ptr) \ 460 p_psMemIncrRefCounter(ptr, __FILE__, __LINE__, __func__) 322 461 #endif // !SWIG 323 462 324 463 #endif // !DOXYGEN 464 325 465 326 466 /** Decrement reference counter and return the pointer … … 331 471 */ 332 472 #ifdef DOXYGEN 473 333 474 psPtr psMemDecrRefCounter( 334 475 psPtr ptr ///< Pointer to decrement refCounter, and return 335 476 ); 477 336 478 #else // DOXYGEN 479 337 480 psPtr p_psMemDecrRefCounter( 338 psPtr vptr, ///< Pointer to decrement refCounter, and return481 psPtr ptr, ///< Pointer to decrement refCounter, and return 339 482 const char *file, ///< File of call 340 psS32 lineno ///< Line number of call 341 ); 342 343 #ifndef SWIG 344 #define psMemDecrRefCounter(vptr) p_psMemDecrRefCounter(vptr, __FILE__, __LINE__) 483 unsigned int lineno, ///< Line number of call 484 const char *func ///< Function name of caller 485 ); 486 487 #ifndef SWIG 488 #define psMemDecrRefCounter(ptr) \ 489 p_psMemDecrRefCounter(ptr, __FILE__, __LINE__, __func__) 345 490 #endif // !SWIG 346 491 347 492 #endif // !DOXYGEN 348 493 494 #if 0 // psMemSetRefCounter 349 495 /** Set reference counter and return the pointer 350 496 * … … 370 516 371 517 #endif // !DOXYGEN 372 373 /** Set callback for problems. 374 * 375 * At various occasions, the memory manager can check the state of the memory 376 * stack. If any of these checks discover that the memory stack is corrupted, 377 * the psMemProblemCallback is called. 378 * 379 * @return psMemProblemCallback old psMemProblemCallback function 380 */ 381 psMemProblemCallback psMemProblemCallbackSet( 382 psMemProblemCallback func ///< Function to run at memory problem detection 383 ); 518 #endif // psMemSetRefCounter 384 519 385 520 /** Set callback for out-of-memory. … … 471 606 /** return statistics on memory usage 472 607 * 473 * @return the total amount of memory owned by psLib; if non-NULL also provide a breakdown474 * into recyclable, allocated,and allocated-and-persistent608 * @return the total amount of memory owned by psLib; if non-NULL also provide 609 * a breakdown into allocated and allocated-and-persistent 475 610 */ 476 611 size_t psMemStats(const bool print, ///< print details as they're found? 477 612 size_t *allocated, ///< memory that's currently allocated (but not persistent) 478 size_t *persistent, ///< persistent memory that's currently allocated 479 size_t *freelist); ///< memory that's waiting to be recycled 613 size_t *persistent); ///< persistent memory that's currently allocated 614 615 /** print detailed information about a psMemBlock 616 * 617 * This function prints a detailed description of a psMemBlock to output. 618 * 619 * @return the return status of fprintf() 620 */ 621 int psMemBlockPrint( 622 FILE *output, ///< FILE to write information too 623 const psMemBlock *memBlock ///< psMemBlock to be examined 624 ); 625 480 626 481 627 /// @} end of SysUtils -
trunk/psLib/src/sys/psTrace.c
r9540 r11265 9 9 * @author GLG, MHPCC 10 10 * 11 * @version $Revision: 1. 79$ $Name: not supported by cvs2svn $12 * @date $Date: 200 6-10-13 22:04:58 $11 * @version $Revision: 1.80 $ $Name: not supported by cvs2svn $ 12 * @date $Date: 2007-01-24 22:14:48 $ 13 13 * 14 14 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 37 37 38 38 *****************************************************************************/ 39 40 #ifdef HAVE_CONFIG_H 41 # include "config.h" 42 #endif 39 43 40 44 #ifndef PS_NO_TRACE … … 80 84 p_psComponent* comp = psAlloc(sizeof(p_psComponent)); 81 85 82 p _psMemSetPersistent(comp,true);86 psMemSetPersistent(comp,true); 83 87 psMemSetDeallocator(comp, (psFreeFunc) componentFree); 84 88 comp->name = psStringCopy(name); 85 p _psMemSetPersistent((psPtr)comp->name,true);89 psMemSetPersistent((psPtr)comp->name,true); 86 90 comp->level = level; 87 91 comp->n = 0; … … 103 107 if (comp->subcomp != NULL) { 104 108 for (psS32 i = 0; i < comp->n; i++) { 105 p _psMemSetPersistent(comp->subcomp[i],false);109 psMemSetPersistent(comp->subcomp[i],false); 106 110 psFree(comp->subcomp[i]); 107 111 } 108 p _psMemSetPersistent(comp->subcomp,false);112 psMemSetPersistent(comp->subcomp,false); 109 113 psFree(comp->subcomp); 110 114 } 111 115 112 p _psMemSetPersistent((psPtr)comp->name,false);116 psMemSetPersistent((psPtr)comp->name,false); 113 117 psFree(comp->name); 114 118 } … … 232 236 currentNode->subcomp = psRealloc(currentNode->subcomp, 233 237 (currentNode->n + 1) * sizeof(p_psComponent* )); 234 p _psMemSetPersistent(currentNode->subcomp,true);238 psMemSetPersistent(currentNode->subcomp,true); 235 239 236 240 currentNode->n = (currentNode->n) + 1; -
trunk/psLib/src/sys/psType.h
r11248 r11265 1 /* @file psType.h 2 * 3 * @brief Contains support for basic types 4 * 5 * This file defines common datatypes used throughout psLib. 6 * 7 * @author Robert DeSonia, MHPCC 8 * @author Ross Harman, MHPCC 9 * 10 * @version $Revision: 1.53 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2007-01-23 22:47:23 $ 12 * 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 14 */ 1 /** @file psType.h 2 * 3 * @brief Contains support for basic types 4 * 5 * This file defines common datatypes used throughout psLib. 6 * 7 * @ingroup DataContainer 8 * 9 * @author Robert DeSonia, MHPCC 10 * @author Ross Harman, MHPCC 11 * 12 * @version $Revision: 1.54 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2007-01-24 22:14:48 $ 14 * 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 16 */ 15 17 16 18 #ifndef PS_TYPE_H … … 298 300 psMath; 299 301 302 /** Checks the deallocator to see if the pointer matches the desired datatype. 303 * 304 * @return bool: True if type matches, otherwise false. 305 */ 306 bool psMemCheckType( 307 psDataType type, ///< The desired psDataType to match 308 psPtr ptr ///< The desired pointer to match 309 ); 310 300 311 /// @} 301 312 #endif // #ifndef PS_TYPE_H -
trunk/psLib/test/math/tap_psPolyFit1D.c
r10848 r11265 318 318 } 319 319 320 psMemCheckCorruption( 1);320 psMemCheckCorruption(stderr, false); 321 321 psFree(myPoly); 322 322 psFree(mask); … … 327 327 psFree(fErr); 328 328 psFree(stats); 329 psMemCheckCorruption( 1);329 psMemCheckCorruption(stderr, false); 330 330 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 331 331 if (0 != memLeaks) { -
trunk/psLib/test/math/tap_psPolyFit2D.c
r10848 r11265 328 328 } 329 329 330 psMemCheckCorruption( 1);330 psMemCheckCorruption(stderr, false); 331 331 psFree(myPoly); 332 332 psFree(mask); … … 339 339 psFree(fErr); 340 340 psFree(stats); 341 psMemCheckCorruption( 1);341 psMemCheckCorruption(stderr, false); 342 342 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 343 343 if (0 != memLeaks) { -
trunk/psLib/test/math/tap_psPolyFit3D.c
r10848 r11265 375 375 } 376 376 377 psMemCheckCorruption( 1);377 psMemCheckCorruption(stderr, false); 378 378 psFree(myPoly); 379 379 psFree(mask); … … 388 388 psFree(fErr); 389 389 psFree(stats); 390 psMemCheckCorruption( 1);390 psMemCheckCorruption(stderr, false); 391 391 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 392 392 if (0 != memLeaks) { -
trunk/psLib/test/math/tap_psPolyFit4D.c
r10848 r11265 431 431 } 432 432 433 psMemCheckCorruption( 1);433 psMemCheckCorruption(stderr, false); 434 434 psFree(myPoly); 435 435 psFree(mask); … … 446 446 psFree(fErr); 447 447 psFree(stats); 448 psMemCheckCorruption( 1);448 psMemCheckCorruption(stderr, false); 449 449 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 450 450 if (0 != memLeaks) { -
trunk/psLib/test/math/tap_psStats07.c
r10848 r11265 484 484 psFree(errors); 485 485 psFree(mask); 486 psMemCheckCorruption( 1);486 psMemCheckCorruption(stderr, false); 487 487 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 488 488 if (0 != memLeaks) { -
trunk/psLib/test/math/tap_psStats09.c
r10848 r11265 335 335 psFree(errors); 336 336 psFree(mask); 337 psMemCheckCorruption( 1);337 psMemCheckCorruption(stderr, false); 338 338 memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); 339 339 if (0 != memLeaks) { -
trunk/psLib/test/mathtypes/tap_psVectorSort_01.c
r10808 r11265 12 12 * @author Ross Harman, MHPCC 13 13 * 14 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $15 * @date $Date: 200 6-12-18 19:10:56$14 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 15 * @date $Date: 2007-01-24 22:14:48 $ 16 16 * 17 17 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 147 147 ok ( ! psMemCheckLeaks(0, NULL, stdout, false),"Memory leaks not detected"); 148 148 149 psS32 nBad = psMemCheckCorruption( 0);149 psS32 nBad = psMemCheckCorruption(stderr, false); 150 150 ok(!nBad, "Found %d bad memory blocks\n", nBad); 151 151 } -
trunk/psLib/test/mathtypes/tap_psVectorSort_02.c
r10808 r11265 14 14 * @author Ross Harman, MHPCC 15 15 * 16 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $17 * @date $Date: 200 6-12-18 19:10:56$16 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 17 * @date $Date: 2007-01-24 22:14:48 $ 18 18 * 19 19 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 130 130 psS32 nLeaks = psMemCheckLeaks(0, NULL, stdout, false); 131 131 ok(!nLeaks, "Found %d memory leaks\n", nLeaks); 132 psS32 nBad = psMemCheckCorruption( 0);132 psS32 nBad = psMemCheckCorruption(stderr, false); 133 133 ok(!nBad, "Found %d bad memory blocks\n", nBad); 134 134 } -
trunk/psLib/test/mathtypes/tap_psVectorSort_03.c
r10808 r11265 12 12 * @author Ross Harman, MHPCC 13 13 * 14 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $15 * @date $Date: 200 6-12-18 19:10:56$14 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 15 * @date $Date: 2007-01-24 22:14:48 $ 16 16 * 17 17 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 68 68 psS32 nLeaks = psMemCheckLeaks(0, NULL, stdout, false); 69 69 ok(!nLeaks, "Found %d memory leaks\n", nLeaks); 70 psS32 nBad = psMemCheckCorruption( 0);70 psS32 nBad = psMemCheckCorruption(stderr, false); 71 71 ok(!nBad, "Found %d bad memory blocks\n", nBad); 72 72 } -
trunk/psLib/test/mathtypes/tap_psVectorSort_04.c
r10808 r11265 9 9 * @author Ross Harman, MHPCC 10 10 * 11 * @version $Revision: 1. 1$ $Name: not supported by cvs2svn $12 * @date $Date: 200 6-12-18 19:10:56$11 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $ 12 * @date $Date: 2007-01-24 22:14:48 $ 13 13 * 14 14 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 37 37 psS32 nLeaks = psMemCheckLeaks(0, NULL, stdout, false); 38 38 ok(!nLeaks, "Found %d memory blocks\n", nLeaks); 39 psS32 nBad = psMemCheckCorruption( 0);39 psS32 nBad = psMemCheckCorruption(stderr, false); 40 40 ok(!nBad, "Found %d bad memory blocks\n", nBad); 41 41 }
Note:
See TracChangeset
for help on using the changeset viewer.
