IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 30, 2004, 4:28:29 PM (22 years ago)
Author:
desonia
Message:

* empty log message *

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/sys/psMemory.c

    r1240 r1360  
    11/** @file  psMemory.c
    2  *
    3  *  @brief Contains the definitions for the memory management system
    4  *
    5  *  psMemory.h has additional information and documentation of the routines found in this file.
    6  *
    7  *  @author Robert DeSonia, MHPCC
    8  *  @author Robert Lupton, Princeton University
    9  *
    10  *  @version $Revision: 1.29 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-07-19 20:45:53 $
    12  *
    13  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    14  */
     2*
     3*  @brief Contains the definitions for the memory management system
     4*
     5*  psMemory.h has additional information and documentation of the routines found in this file.
     6*
     7*  @author Robert DeSonia, MHPCC
     8*  @author Robert Lupton, Princeton University
     9*
     10*  @version $Revision: 1.30 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2004-07-31 02:28:10 $
     12*
     13*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     14*/
    1515
    1616#define PS_ALLOW_MALLOC                 // we're allowed to call malloc()
     
    3030#define P_PS_LARGE_BLOCK_SIZE 65536    // size where under, we try to recycle
    3131
    32 static int checkMemBlock(const psMemBlock *m, const char* funcName);
     32static int checkMemBlock( const psMemBlock *m, const char* funcName );
    3333static psMemBlock *lastMemBlockAllocated = NULL;
    3434static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
     
    3838
    3939static int recycleBins = 13;
    40 static int recycleBinSize[14] = {8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,P_PS_LARGE_BLOCK_SIZE};
     40static int recycleBinSize[ 14 ] =
     41    {
     42        8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE
     43    };
    4144// N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops)
    42 static psMemBlock* recycleMemBlockList[13] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
    43 
     45static psMemBlock* recycleMemBlockList[ 13 ] =
     46    {
     47        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
     48    };
     49   
    4450#ifdef PS_MEM_DEBUG
    4551static psMemBlock* deadBlockList;    // a place to put dead memBlocks in debug mode.
     
    5359 *  Default memExhausted callback.
    5460 */
    55 static void *memExhaustedCallbackDefault(size_t size)
    56 {
    57     void* ptr = NULL;
    58 
    59     pthread_mutex_lock(&recycleMemBlockListMutex);
    60     int level=recycleBins-1;
    61     while (level >= 0 && ptr == NULL) {
    62         while (recycleMemBlockList[level] != NULL && ptr == NULL) {
    63             psMemBlock* old = recycleMemBlockList[level];
    64             recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;
    65             free(old);
    66             ptr = malloc(size);
    67         }
    68         level--;
    69     }
    70     pthread_mutex_unlock(&recycleMemBlockListMutex);
    71 
     61static void *memExhaustedCallbackDefault( size_t size )
     62{
     63    void * ptr = NULL;
     64   
     65    pthread_mutex_lock( &recycleMemBlockListMutex );
     66    int level = recycleBins - 1;
     67    while ( level >= 0 && ptr == NULL ) {
     68            while ( recycleMemBlockList[ level ] != NULL && ptr == NULL ) {
     69                    psMemBlock * old = recycleMemBlockList[ level ];
     70                    recycleMemBlockList[ level ] = recycleMemBlockList[ level ] ->nextBlock;
     71                    free( old );
     72                    ptr = malloc( size );
     73                }
     74            level--;
     75        }
     76    pthread_mutex_unlock( &recycleMemBlockListMutex );
     77   
    7278    return ptr;
    7379}
     
    7581static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault;
    7682
    77 psMemExhaustedCallback psMemExhaustedCallbackSet(psMemExhaustedCallback func)
     83psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func )
    7884{
    7985    psMemExhaustedCallback old = memExhaustedCallback;
    80 
    81     if (func != NULL) {
    82         memExhaustedCallback = func;
    83     } else {
    84         memExhaustedCallback = memExhaustedCallbackDefault;
    85     }
    86 
     86   
     87    if ( func != NULL ) {
     88            memExhaustedCallback = func;
     89        } else {
     90            memExhaustedCallback = memExhaustedCallbackDefault;
     91        }
     92       
    8793    return old;
    8894}
    8995
    90 static void memProblemCallbackDefault(const psMemBlock *ptr,
    91                                       const char *file, int lineno)
    92 {
    93     if (ptr->refCounter < 1) {
    94         psError(__func__,
    95                 "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
    96                 ptr->id, ptr->file, ptr->lineno, file, lineno);
    97     }
    98 
    99     if (lineno > 0) {
    100         psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);
    101     }
     96static void memProblemCallbackDefault( const psMemBlock *ptr,
     97                                       const char *file, int lineno )
     98{
     99    if ( ptr->refCounter < 1 ) {
     100            psError( __func__,
     101                     "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
     102                     ptr->id, ptr->file, ptr->lineno, file, lineno );
     103        }
     104       
     105    if ( lineno > 0 ) {
     106            psAbort( __func__, "Detected a problem in the memory system at %s:%d", file, lineno );
     107        }
    102108}
    103109static psMemProblemCallback memProblemCallback = memProblemCallbackDefault;
    104110
    105 psMemProblemCallback psMemProblemCallbackSet(psMemProblemCallback func)
     111psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func )
    106112{
    107113    psMemProblemCallback old = memProblemCallback;
    108 
    109     if (func != NULL) {
    110         memProblemCallback = func;
    111     } else {
    112         memProblemCallback = memProblemCallbackDefault;
    113     }
    114 
     114   
     115    if ( func != NULL ) {
     116            memProblemCallback = func;
     117        } else {
     118            memProblemCallback = memProblemCallbackDefault;
     119        }
     120       
    115121    return old;
    116122}
     
    123129psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
    124130
    125 psMemoryId psMemAllocateCallbackSetID(psMemoryId id)
     131psMemoryId psMemAllocateCallbackSetID( psMemoryId id )
    126132{
    127133    psMemoryId old = p_psMemAllocateID;
    128134    p_psMemAllocateID = id;
    129 
     135   
    130136    return old;
    131137}
    132138
    133 psMemoryId psMemFreeCallbackSetID(psMemoryId id)
     139psMemoryId psMemFreeCallbackSetID( psMemoryId id )
    134140{
    135141    psMemoryId old = p_psMemFreeID;
    136142    p_psMemFreeID = id;
    137 
     143   
    138144    return old;
    139145}
     
    145151 * isn't resignalled)
    146152 */
    147 static psMemoryId memAllocateCallbackDefault(const psMemBlock *ptr)
     153static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr )
    148154{
    149155    static psMemoryId incr = 0;  // "p_psMemAllocateID += incr"
    150 
     156   
    151157    return incr;
    152158}
    153159
    154 static psMemoryId memFreeCallbackDefault(const psMemBlock *ptr)
     160static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr )
    155161{
    156162    static psMemoryId incr = 0;  // "p_psMemFreeID += incr"
    157 
     163   
    158164    return incr;
    159165}
     
    165171static psMemFreeCallback memFreeCallback = memFreeCallbackDefault;
    166172
    167 psMemAllocateCallback psMemAllocateCallbackSet(psMemAllocateCallback func)
     173psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func )
    168174{
    169175    psMemFreeCallback old = memAllocateCallback;
    170 
    171     if (func != NULL) {
    172         memAllocateCallback = func;
    173     } else {
    174         memAllocateCallback = memAllocateCallbackDefault;
    175     }
    176 
     176   
     177    if ( func != NULL ) {
     178            memAllocateCallback = func;
     179        } else {
     180            memAllocateCallback = memAllocateCallbackDefault;
     181        }
     182       
    177183    return old;
    178184}
    179185
    180 psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func)
     186psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func )
    181187{
    182188    psMemFreeCallback old = memFreeCallback;
    183 
    184     if (func != NULL) {
    185         memFreeCallback = func;
    186     } else {
    187         memFreeCallback = memFreeCallbackDefault;
    188     }
    189 
     189   
     190    if ( func != NULL ) {
     191            memFreeCallback = func;
     192        } else {
     193            memFreeCallback = memFreeCallbackDefault;
     194        }
     195       
    190196    return old;
    191197}
     
    194200 * Return memory ID counter for next block to be allocated
    195201 */
    196 psMemoryId psMemGetId(void)
     202psMemoryId psMemGetId( void )
    197203{
    198204    psMemoryId id;
    199     pthread_mutex_lock(&memIdMutex);
     205    pthread_mutex_lock( &memIdMutex );
    200206    id = memid + 1;
    201     pthread_mutex_unlock(&memIdMutex);
    202 
     207    pthread_mutex_unlock( &memIdMutex );
     208   
    203209    return id;
    204210}
     
    210216 */
    211217
    212 static int checkMemBlock(const psMemBlock *m, const char* funcName)
     218static int checkMemBlock( const psMemBlock *m, const char* funcName )
    213219{
    214220    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
    215221    // we shouldn't call such things as p_psAlloc/p_psFree here.
    216 
    217     if (m == NULL) {
    218         psError(funcName,"Memory Corruption: NULL memory block found.");
    219         return 1;
    220     }
    221 
    222     if (m->refCounter == 0) {
    223         // using an unreferenced block of memory, are you?
    224         psError(__func__,"Memory Corruption: memory block %ld was freed but still used.",
    225                 m->id);
    226         return 1;
    227     }
    228 
    229     if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
    230         psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)",
    231                 m->id);
    232         return 1;
    233     }
    234     if (*(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {
    235         psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)",
    236                 m->id);
    237         return 1;
    238     }
    239 
     222   
     223    if ( m == NULL ) {
     224            psError( funcName, "Memory Corruption: NULL memory block found." );
     225            return 1;
     226        }
     227       
     228    if ( m->refCounter == 0 ) {
     229            // using an unreferenced block of memory, are you?
     230            psError( __func__, "Memory Corruption: memory block %ld was freed but still used.",
     231                     m->id );
     232            return 1;
     233        }
     234       
     235    if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC ) {
     236            psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)",
     237                     m->id );
     238            return 1;
     239        }
     240    if ( *( void** ) ( ( int8_t* ) ( m + 1 ) + m->userMemorySize ) != P_PS_MEMMAGIC ) {
     241            psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)",
     242                     m->id );
     243            return 1;
     244        }
     245       
    240246    return 0;
    241247}
    242248
    243 int psMemCheckCorruption(bool abort_on_error)
     249int psMemCheckCorruption( bool abort_on_error )
    244250{
    245251    int nbad = 0;                       // number of bad blocks
    246 
     252   
    247253    // get exclusive access to the memBlock list to avoid it changing on us while we use it.
    248     pthread_mutex_lock(&memBlockListMutex);
    249 
    250     for (psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {
    251         if (checkMemBlock(iter, __func__)) {
    252             nbad++;
    253 
    254             memProblemCallback(iter, __func__, __LINE__);
    255 
    256             if (abort_on_error) {
    257                 // release the lock on the memblock list
    258                 pthread_mutex_unlock(&memBlockListMutex);
    259                 psAbort(__func__, "Detected memory corruption");
    260                 return nbad;
    261             }
    262         }
    263     }
    264 
     254    pthread_mutex_lock( &memBlockListMutex );
     255   
     256    for ( psMemBlock * iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock ) {
     257            if ( checkMemBlock( iter, __func__ ) ) {
     258                    nbad++;
     259                   
     260                    memProblemCallback( iter, __func__, __LINE__ );
     261                   
     262                    if ( abort_on_error ) {
     263                            // release the lock on the memblock list
     264                            pthread_mutex_unlock( &memBlockListMutex );
     265                            psAbort( __func__, "Detected memory corruption" );
     266                            return nbad;
     267                        }
     268                }
     269        }
     270       
    265271    // release the lock on the memblock list
    266     pthread_mutex_unlock(&memBlockListMutex);
     272    pthread_mutex_unlock( &memBlockListMutex );
    267273    return nbad;
    268274}
    269275
    270 void *p_psAlloc(size_t size, const char *file, int lineno)
    271 {
    272 
    273     psMemBlock *ptr = NULL;
    274 
     276void *p_psAlloc( size_t size, const char *file, int lineno )
     277{
     278
     279    psMemBlock * ptr = NULL;
     280   
    275281    // memory is of the size I want to bother recycling?
    276     if (size < P_PS_LARGE_BLOCK_SIZE) {
    277         // find the bin we need.
    278         int level = 0;
    279         while (size > recycleBinSize[level]) {
    280             level++;
    281         }
    282         // Are we in one of the bins
    283         if (level<recycleBins) {
    284 
    285             size = recycleBinSize[level];  // round-up size to next sized bin.
    286 
    287             pthread_mutex_lock(&recycleMemBlockListMutex);
    288 
    289             if (recycleMemBlockList[level] != NULL) {
    290                 ptr = recycleMemBlockList[level];
    291                 recycleMemBlockList[level] = ptr->nextBlock;
    292                 if (recycleMemBlockList[level] != NULL) {
    293                     recycleMemBlockList[level]->previousBlock = NULL;
    294                 }
    295                 size = ptr->userMemorySize;
    296             }
    297 
    298             pthread_mutex_unlock(&recycleMemBlockListMutex);
    299         }
    300     }
    301 
    302     if (ptr == NULL) {
    303         ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));
    304 
    305         if (ptr == NULL) {
    306             ptr = memExhaustedCallback(size);
    307             if (ptr == NULL) {
    308                 psAbort(__func__, "Failed to allocate %u bytes at %s:%d",
    309                         size, file, lineno);
    310             }
    311         }
    312 
    313         ptr->startblock = P_PS_MEMMAGIC;
    314         ptr->endblock = P_PS_MEMMAGIC;
    315         ptr->userMemorySize = size;
    316         pthread_mutex_init(&ptr->refCounterMutex, NULL);
    317     }
    318 
     282    if ( size < P_PS_LARGE_BLOCK_SIZE ) {
     283            // find the bin we need.
     284            int level = 0;
     285            while ( size > recycleBinSize[ level ] ) {
     286                    level++;
     287                }
     288            // Are we in one of the bins
     289            if ( level < recycleBins ) {
     290           
     291                    size = recycleBinSize[ level ];  // round-up size to next sized bin.
     292                   
     293                    pthread_mutex_lock( &recycleMemBlockListMutex );
     294                   
     295                    if ( recycleMemBlockList[ level ] != NULL ) {
     296                            ptr = recycleMemBlockList[ level ];
     297                            recycleMemBlockList[ level ] = ptr->nextBlock;
     298                            if ( recycleMemBlockList[ level ] != NULL ) {
     299                                    recycleMemBlockList[ level ] ->previousBlock = NULL;
     300                                }
     301                            size = ptr->userMemorySize;
     302                        }
     303                       
     304                    pthread_mutex_unlock( &recycleMemBlockListMutex );
     305                }
     306        }
     307       
     308    if ( ptr == NULL ) {
     309            ptr = malloc( sizeof( psMemBlock ) + size + sizeof( void* ) );
     310           
     311            if ( ptr == NULL ) {
     312                    ptr = memExhaustedCallback( size );
     313                    if ( ptr == NULL ) {
     314                            psAbort( __func__, "Failed to allocate %u bytes at %s:%d",
     315                                     size, file, lineno );
     316                        }
     317                }
     318               
     319            ptr->startblock = P_PS_MEMMAGIC;
     320            ptr->endblock = P_PS_MEMMAGIC;
     321            ptr->userMemorySize = size;
     322            pthread_mutex_init( &ptr->refCounterMutex, NULL );
     323        }
     324       
    319325    // increment the memory id safely.
    320     pthread_mutex_lock(&memBlockListMutex);
    321     *(psMemoryId*)&ptr->id = ++memid;
    322     pthread_mutex_unlock(&memBlockListMutex);
    323 
     326    pthread_mutex_lock( &memBlockListMutex );
     327    *( psMemoryId* ) & ptr->id = ++memid;
     328    pthread_mutex_unlock( &memBlockListMutex );
     329   
    324330    ptr->file = file;
    325331    ptr->freeFcn = NULL;
    326     *(unsigned int*)&ptr->lineno = lineno;
    327     *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
     332    *( unsigned int* ) & ptr->lineno = lineno;
     333    *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC;
    328334    ptr->previousBlock = NULL;
    329 
     335   
    330336    ptr->refCounter = 1;                // one user so far
    331 
     337   
    332338    // need exclusive access of the memory block list now...
    333     pthread_mutex_lock(&memBlockListMutex);
    334 
     339    pthread_mutex_lock( &memBlockListMutex );
     340   
    335341    // insert the new block to the front of the memBlock linked-list
    336342    ptr->nextBlock = lastMemBlockAllocated;
    337     if (ptr->nextBlock != NULL) {
    338         ptr->nextBlock->previousBlock = ptr;
    339     }
     343    if ( ptr->nextBlock != NULL ) {
     344            ptr->nextBlock->previousBlock = ptr;
     345        }
    340346    lastMemBlockAllocated = ptr;
    341 
    342     pthread_mutex_unlock(&memBlockListMutex);
    343 
     347   
     348    pthread_mutex_unlock( &memBlockListMutex );
     349   
    344350    //  Did the user ask to be informed about this allocation?
    345     if (ptr->id == p_psMemAllocateID) {
    346         p_psMemAllocateID += memAllocateCallback(ptr);
    347     }
    348 
     351    if ( ptr->id == p_psMemAllocateID ) {
     352            p_psMemAllocateID += memAllocateCallback( ptr );
     353        }
     354       
    349355    // And return the user the memory that they allocated
    350356    return ptr + 1;   // user memory
    351357}
    352358
    353 void *p_psRealloc(void *vptr, size_t size, const char *file, int lineno)
    354 {
    355     if (vptr == NULL) {
    356         return p_psAlloc(size, file, lineno);
    357     } else {
    358         psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    359         bool isBlockLast = false;
    360 
    361         if (checkMemBlock(ptr, __func__) != 0) {
    362             memProblemCallback(ptr, file, lineno);
    363             psAbort(file,"Realloc detected a memory corruption (id %ld @ %s:%d).",
    364                     ptr->id,ptr->file,ptr->lineno);
    365         }
    366 
    367         pthread_mutex_lock(&memBlockListMutex);
    368 
    369         isBlockLast = (ptr == lastMemBlockAllocated);
    370 
    371         ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));
    372 
    373         if (ptr == NULL) {
    374             psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d",
    375                     size, file, lineno);
    376         }
    377 
    378         ptr->userMemorySize = size;
    379         *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    380 
    381         if (isBlockLast) {
    382             lastMemBlockAllocated = ptr;
    383         }
    384 
    385         // the block location may have changed, so fix the linked list addresses.
    386         if (ptr->nextBlock != NULL) {
    387             ptr->nextBlock->previousBlock = ptr;
    388         }
    389         if (ptr->previousBlock != NULL) {
    390             ptr->previousBlock->nextBlock = ptr;
    391         }
    392 
    393         pthread_mutex_unlock(&memBlockListMutex);
    394 
    395         //  Did the user ask to be informed about this allocation?
    396         if (ptr->id == p_psMemAllocateID) {
    397             p_psMemAllocateID += memAllocateCallback(ptr);
    398         }
    399 
    400         return ptr + 1;   // usr memory
    401     }
    402 }
    403 
    404 void p_psFree(void *vptr, const char *file, int lineno)
    405 {
    406     (void)p_psMemDecrRefCounter(vptr,file,lineno);   // this handles the free, if required.
     359void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno )
     360{
     361    if ( vptr == NULL ) {
     362            return p_psAlloc( size, file, lineno );
     363        } else {
     364            psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1;
     365            bool isBlockLast = false;
     366           
     367            if ( checkMemBlock( ptr, __func__ ) != 0 ) {
     368                    memProblemCallback( ptr, file, lineno );
     369                    psAbort( file, "Realloc detected a memory corruption (id %ld @ %s:%d).",
     370                             ptr->id, ptr->file, ptr->lineno );
     371                }
     372               
     373            pthread_mutex_lock( &memBlockListMutex );
     374           
     375            isBlockLast = ( ptr == lastMemBlockAllocated );
     376           
     377            ptr = ( psMemBlock* ) realloc( ptr, sizeof( psMemBlock ) + size + sizeof( void* ) );
     378           
     379            if ( ptr == NULL ) {
     380                    psAbort( __func__, "Failed to reallocate %ld bytes at %s:%d",
     381                             size, file, lineno );
     382                }
     383               
     384            ptr->userMemorySize = size;
     385            *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC;
     386           
     387            if ( isBlockLast ) {
     388                    lastMemBlockAllocated = ptr;
     389                }
     390               
     391            // the block location may have changed, so fix the linked list addresses.
     392            if ( ptr->nextBlock != NULL ) {
     393                    ptr->nextBlock->previousBlock = ptr;
     394                }
     395            if ( ptr->previousBlock != NULL ) {
     396                    ptr->previousBlock->nextBlock = ptr;
     397                }
     398               
     399            pthread_mutex_unlock( &memBlockListMutex );
     400           
     401            //  Did the user ask to be informed about this allocation?
     402            if ( ptr->id == p_psMemAllocateID ) {
     403                    p_psMemAllocateID += memAllocateCallback( ptr );
     404                }
     405               
     406            return ptr + 1;   // usr memory
     407        }
     408}
     409
     410void p_psFree( void *vptr, const char *file, int lineno )
     411{
     412    ( void ) p_psMemDecrRefCounter( vptr, file, lineno );   // this handles the free, if required.
    407413}
    408414
     
    410416 * Check for memory leaks.
    411417 */
    412 int psMemCheckLeaks(psMemoryId id0,psMemBlock ***arr,FILE *fd)
     418int psMemCheckLeaks( psMemoryId id0, psMemBlock ***arr, FILE *fd )
    413419{
    414420    int nleak = 0;
    415421    int j = 0;
    416422    psMemBlock* topBlock = lastMemBlockAllocated;
    417 
    418     pthread_mutex_lock(&memBlockListMutex);
    419 
    420     for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {
    421         if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {
    422             nleak++;
    423 
    424             if (fd != NULL) {
    425                 if (nleak == 1) {
    426                     fprintf(fd, "   %20s:line ID\n", "file");
    427                 }
    428 
    429                 fprintf(fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);
    430             }
    431         }
    432     }
    433 
    434     pthread_mutex_unlock(&memBlockListMutex);
    435 
    436     if (nleak == 0 || arr == NULL) {
    437         return nleak;
    438     }
    439 
    440     *arr = p_psAlloc(nleak*sizeof(psMemBlock), __FILE__, __LINE__);
    441     pthread_mutex_lock(&memBlockListMutex);
    442 
    443     for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {
    444         if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {
    445             (*arr)[j++] = iter;
    446             if (j == nleak) { // found them all
    447                 break;
    448             }
    449         }
    450     }
    451 
    452     pthread_mutex_unlock(&memBlockListMutex);
    453 
     423   
     424    pthread_mutex_lock( &memBlockListMutex );
     425   
     426    for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) {
     427            if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) {
     428                    nleak++;
     429                   
     430                    if ( fd != NULL ) {
     431                            if ( nleak == 1 ) {
     432                                    fprintf( fd, "   %20s:line ID\n", "file" );
     433                                }
     434                               
     435                            fprintf( fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id );
     436                        }
     437                }
     438        }
     439       
     440    pthread_mutex_unlock( &memBlockListMutex );
     441   
     442    if ( nleak == 0 || arr == NULL ) {
     443            return nleak;
     444        }
     445       
     446    *arr = p_psAlloc( nleak * sizeof( psMemBlock ), __FILE__, __LINE__ );
     447    pthread_mutex_lock( &memBlockListMutex );
     448   
     449    for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) {
     450            if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) {
     451                    ( *arr ) [ j++ ] = iter;
     452                    if ( j == nleak ) { // found them all
     453                            break;
     454                        }
     455                }
     456        }
     457       
     458    pthread_mutex_unlock( &memBlockListMutex );
     459   
    454460    return nleak;
    455461}
     
    457463/*
    458464 * Reference counting APIs
    459  */
     465 */ 
    460466// return refCounter
    461 psReferenceCount psMemGetRefCounter(void *vptr)
    462 {
    463     psMemBlock *ptr;
     467psReferenceCount psMemGetRefCounter( void *vptr )
     468{
     469    psMemBlock * ptr;
    464470    unsigned int refCount;
    465 
    466     if (vptr == NULL) {
    467         return 0;
    468     }
    469 
    470     ptr = ((psMemBlock *)vptr) - 1;
    471 
    472     if (checkMemBlock(ptr, __func__) != 0) {
    473         memProblemCallback(ptr, __func__, __LINE__);
    474     }
    475 
    476     pthread_mutex_lock(&ptr->refCounterMutex);
     471   
     472    if ( vptr == NULL ) {
     473            return 0;
     474        }
     475       
     476    ptr = ( ( psMemBlock * ) vptr ) - 1;
     477   
     478    if ( checkMemBlock( ptr, __func__ ) != 0 ) {
     479            memProblemCallback( ptr, __func__, __LINE__ );
     480        }
     481       
     482    pthread_mutex_lock( &ptr->refCounterMutex );
    477483    refCount = ptr->refCounter;
    478     pthread_mutex_unlock(&ptr->refCounterMutex);
    479 
     484    pthread_mutex_unlock( &ptr->refCounterMutex );
     485   
    480486    return refCount;
    481487}
    482488// increment and return refCounter
    483 void* p_psMemIncrRefCounter(void *vptr, const char *file, int lineno)
    484 {
    485     psMemBlock *ptr;
    486 
    487     if (vptr == NULL) {
    488         return vptr;
    489     }
    490 
    491     ptr = ((psMemBlock *)vptr) - 1;
    492 
    493     if (checkMemBlock(ptr, __func__)) {
    494         memProblemCallback(ptr, file,lineno);
    495     }
    496 
    497     pthread_mutex_lock(&ptr->refCounterMutex);
     489void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno )
     490{
     491    psMemBlock * ptr;
     492   
     493    if ( vptr == NULL ) {
     494            return vptr;
     495        }
     496       
     497    ptr = ( ( psMemBlock * ) vptr ) - 1;
     498   
     499    if ( checkMemBlock( ptr, __func__ ) ) {
     500            memProblemCallback( ptr, file, lineno );
     501        }
     502       
     503    pthread_mutex_lock( &ptr->refCounterMutex );
    498504    ptr->refCounter++;
    499     pthread_mutex_unlock(&ptr->refCounterMutex);
    500 
     505    pthread_mutex_unlock( &ptr->refCounterMutex );
     506   
    501507    return vptr;
    502508}
    503509
    504510// decrement and return refCounter
    505 void* p_psMemDecrRefCounter(void *vptr,const char *file, int lineno)
    506 {
    507     if (vptr == NULL) {
    508         return NULL;
    509     }
    510 
    511     psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    512 
    513     if (checkMemBlock(ptr, __func__) != 0) {
    514         memProblemCallback(ptr, file, lineno);
    515         return NULL;
    516     }
    517 
    518     pthread_mutex_lock(&ptr->refCounterMutex);
    519 
    520     if (ptr->refCounter > 1) {
    521         /// XXX - Probably should have another mutex here.
    522         ptr->refCounter--;          // multiple references, just decrement the count.
    523         pthread_mutex_unlock(&ptr->refCounterMutex);
    524 
    525     } else {
    526         pthread_mutex_unlock(&ptr->refCounterMutex);
    527 
    528         // Did the user ask to be informed about this deallocation?
    529         if (ptr->id == p_psMemFreeID) {
    530             p_psMemFreeID += memFreeCallback(ptr);
    531         }
    532 
    533         if (ptr->freeFcn != NULL) {
    534             ptr->freeFcn(vptr);
    535         }
    536 
    537         pthread_mutex_lock(&memBlockListMutex);
    538 
    539         // cut the memBlock out of the memBlock list
    540         if (ptr->nextBlock != NULL) {
    541             ptr->nextBlock->previousBlock = ptr->previousBlock;
    542         }
    543         if (ptr->previousBlock != NULL) {
    544             ptr->previousBlock->nextBlock = ptr->nextBlock;
    545         }
    546         if (lastMemBlockAllocated == ptr) {
    547             lastMemBlockAllocated = ptr->nextBlock;
    548         }
    549 
    550         pthread_mutex_unlock(&memBlockListMutex);
    551 
    552 
    553         // do we need to recycle?
    554         if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) {
    555 
    556             int level = 1;
    557             while (ptr->userMemorySize >= recycleBinSize[level]) {
    558                 level++;
    559             }
    560             level--;
    561 
    562             ptr->refCounter = 0;
    563             ptr->previousBlock = NULL;
    564 
    565             pthread_mutex_lock(&recycleMemBlockListMutex);
    566             ptr->nextBlock = recycleMemBlockList[level];
    567             if (recycleMemBlockList[level] != NULL) {
    568                 recycleMemBlockList[level]->previousBlock = ptr;
    569             }
    570             recycleMemBlockList[level] = ptr;
    571             pthread_mutex_unlock(&recycleMemBlockListMutex);
    572 
     511void* p_psMemDecrRefCounter( void *vptr, const char *file, int lineno )
     512{
     513    if ( vptr == NULL ) {
     514            return NULL;
     515        }
     516       
     517    psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1;
     518   
     519    if ( checkMemBlock( ptr, __func__ ) != 0 ) {
     520            memProblemCallback( ptr, file, lineno );
     521            return NULL;
     522        }
     523       
     524    pthread_mutex_lock( &ptr->refCounterMutex );
     525   
     526    if ( ptr->refCounter > 1 ) {
     527            /// XXX - Probably should have another mutex here.
     528            ptr->refCounter--;          // multiple references, just decrement the count.
     529            pthread_mutex_unlock( &ptr->refCounterMutex );
     530           
    573531        } else {
    574             // memory is larger than I want to recycle.
    575             #ifdef PS_MEM_DEBUG
    576             (void)p_psRealloc(vptr,0,file,lineno);
    577             ptr->previousBlock = NULL;
    578             ptr->nextBlock = deadBlockList;
    579             if (deadBlockList != NULL) {
    580                 deadBlockList->previous = ptr;
    581             }
    582             deadBlockList = ptr;
    583             #else
    584 
    585             pthread_mutex_destroy(&ptr->refCounterMutex);
    586             free(ptr);
    587             #endif
    588 
    589         }
    590 
    591 
    592         pthread_mutex_destroy(&ptr->refCounterMutex);
    593 
    594 
    595         vptr = NULL;    // since we freed it, make sure we return NULL.
    596     }
    597 
     532            pthread_mutex_unlock( &ptr->refCounterMutex );
     533           
     534            // Did the user ask to be informed about this deallocation?
     535            if ( ptr->id == p_psMemFreeID ) {
     536                    p_psMemFreeID += memFreeCallback( ptr );
     537                }
     538               
     539            if ( ptr->freeFcn != NULL ) {
     540                    ptr->freeFcn( vptr );
     541                }
     542               
     543            pthread_mutex_lock( &memBlockListMutex );
     544           
     545            // cut the memBlock out of the memBlock list
     546            if ( ptr->nextBlock != NULL ) {
     547                    ptr->nextBlock->previousBlock = ptr->previousBlock;
     548                }
     549            if ( ptr->previousBlock != NULL ) {
     550                    ptr->previousBlock->nextBlock = ptr->nextBlock;
     551                }
     552            if ( lastMemBlockAllocated == ptr ) {
     553                    lastMemBlockAllocated = ptr->nextBlock;
     554                }
     555               
     556            pthread_mutex_unlock( &memBlockListMutex );
     557           
     558           
     559            // do we need to recycle?
     560            if ( ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE ) {
     561           
     562                    int level = 1;
     563                    while ( ptr->userMemorySize >= recycleBinSize[ level ] ) {
     564                            level++;
     565                        }
     566                    level--;
     567                   
     568                    ptr->refCounter = 0;
     569                    ptr->previousBlock = NULL;
     570                   
     571                    pthread_mutex_lock( &recycleMemBlockListMutex );
     572                    ptr->nextBlock = recycleMemBlockList[ level ];
     573                    if ( recycleMemBlockList[ level ] != NULL ) {
     574                            recycleMemBlockList[ level ] ->previousBlock = ptr;
     575                        }
     576                    recycleMemBlockList[ level ] = ptr;
     577                    pthread_mutex_unlock( &recycleMemBlockListMutex );
     578                   
     579                } else {
     580                    // memory is larger than I want to recycle.
     581                    #ifdef PS_MEM_DEBUG
     582                    ( void ) p_psRealloc( vptr, 0, file, lineno );
     583                    ptr->previousBlock = NULL;
     584                    ptr->nextBlock = deadBlockList;
     585                    if ( deadBlockList != NULL ) {
     586                            deadBlockList->previous = ptr;
     587                        }
     588                    deadBlockList = ptr;
     589                    #else
     590                   
     591                    pthread_mutex_destroy( &ptr->refCounterMutex );
     592                    free( ptr );
     593                    #endif
     594                   
     595                }
     596               
     597            vptr = NULL;    // since we freed it, make sure we return NULL.
     598        }
     599       
    598600    return vptr;
    599601}
    600602
    601 void p_psMemSetDeallocator(void* vptr, psFreeFcn freeFcn)
    602 {
    603     if (vptr == NULL) {
    604         return;
    605     }
    606 
    607     psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    608 
    609     if (checkMemBlock(ptr, __func__) != 0) {
    610         memProblemCallback(ptr, __func__, __LINE__);
    611     }
    612 
     603void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn )
     604{
     605    if ( vptr == NULL ) {
     606            return ;
     607        }
     608       
     609    psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1;
     610   
     611    if ( checkMemBlock( ptr, __func__ ) != 0 ) {
     612            memProblemCallback( ptr, __func__, __LINE__ );
     613        }
     614       
    613615    ptr->freeFcn = freeFcn;
    614 
    615 }
    616 psFreeFcn p_psMemGetDeallocator(void* vptr)
    617 {
    618     if (vptr == NULL) {
    619         return NULL;
    620     }
    621 
    622     psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    623 
    624     if (checkMemBlock(ptr, __func__) != 0) {
    625         memProblemCallback(ptr, __func__, __LINE__);
    626     }
    627 
     616   
     617}
     618psFreeFcn p_psMemGetDeallocator( void* vptr )
     619{
     620    if ( vptr == NULL ) {
     621            return NULL;
     622        }
     623       
     624    psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1;
     625   
     626    if ( checkMemBlock( ptr, __func__ ) != 0 ) {
     627            memProblemCallback( ptr, __func__, __LINE__ );
     628        }
     629       
    628630    return ptr->freeFcn;
    629631}
Note: See TracChangeset for help on using the changeset viewer.