00001
00002
00003
00004
00005
00006
00007 #include "mcw_malloc.h"
00008 #include "Amalloc.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017 #define MAGIC ((char) 0xd7)
00018 #define NEXTRA (2*sizeof(int))
00019
00020 #undef malloc
00021 #undef realloc
00022 #undef calloc
00023 #undef free
00024 #undef XtMalloc
00025 #undef XtRealloc
00026 #undef XtFree
00027 #undef XtCalloc
00028 #undef mcw_malloc
00029 #undef mcw_realloc
00030 #undef mcw_calloc
00031 #undef mcw_free
00032
00033 #undef UINT
00034 #define UINT unsigned int
00035
00036 #ifdef USE_TRACING
00037 # include "debugtrace.h"
00038 # undef NTB
00039 # define NTB 5
00040 #endif
00041
00042
00043
00044 typedef struct {
00045 void * pmt ;
00046 size_t psz ;
00047 char * pfn ;
00048 int pln ;
00049 UINT pss ;
00050 #ifdef USE_TRACING
00051 char * ptb[NTB] ;
00052 #endif
00053 } mallitem ;
00054
00055
00056
00057
00058
00059 #define SLOTS 8191
00060
00061
00062
00063
00064 static mallitem ** htab = NULL ;
00065 static int * nhtab = NULL ;
00066 static UINT serial = 0 ;
00067
00068 #undef INLINE
00069 #ifdef __GNUC__
00070 # define INLINE inline
00071 #else
00072 # define INLINE
00073 #endif
00074
00075 #ifdef USE_TRACING
00076 # define ADD_TRACEBACK(ip) \
00077 do{ int tt ; \
00078 for( tt=1 ; tt <= NTB ; tt++ ) \
00079 ip->ptb[tt-1] = (tt < DBG_num) ? DBG_rout[DBG_num-tt] : NULL; } while(0)
00080 #else
00081 # define ADD_TRACEBACK(ip)
00082 #endif
00083
00084
00085
00086
00087
00088 static INLINE UINT mallkey( char * fred )
00089 {
00090 UINT q = ((UINT) fred) ;
00091
00092 q = ((q & 0xf0f0f0f0) >> 4)
00093 | ((q & 0x0f0f0f0f) << 4) ;
00094
00095 return q ;
00096 }
00097
00098
00099
00100
00101
00102
00103 static mallitem * ptr_tracker( void * fred )
00104 {
00105 int jj,kk ;
00106
00107 if( fred == NULL ) return NULL ;
00108
00109 jj = mallkey((char *)fred) % SLOTS ;
00110
00111 if( htab[jj] == NULL ) return NULL ;
00112
00113 for( kk=0 ; kk < nhtab[jj] ; kk++ )
00114 if( htab[jj][kk].pmt == fred ) return (htab[jj]+kk) ;
00115
00116 return NULL ;
00117 }
00118
00119
00120
00121
00122 #define shift_tracker(fff) ptr_tracker( ((char *)(fff)) - NEXTRA )
00123
00124
00125
00126
00127
00128
00129 static mallitem * find_empty_slot( int jj )
00130 {
00131 int kk ;
00132
00133 if( htab[jj] == NULL ){
00134 htab[jj] = (mallitem *) malloc(sizeof(mallitem)) ;
00135 nhtab[jj] = 1 ;
00136 kk = 0 ;
00137 htab[jj][0].pmt = NULL ;
00138 } else {
00139 for( kk=nhtab[jj]-1 ; kk >= 0 ; kk-- )
00140 if( htab[jj][kk].pmt == NULL ) break ;
00141
00142 if( kk < 0 ){
00143 kk = nhtab[jj] ; nhtab[jj]++ ;
00144 htab[jj] = (mallitem *) realloc( htab[jj], sizeof(mallitem)*nhtab[jj] ) ;
00145 htab[jj][kk].pmt = NULL ;
00146 }
00147 }
00148
00149 return (htab[jj]+kk) ;
00150 }
00151
00152
00153
00154
00155
00156
00157 static void add_tracker( void * fred , size_t n , char * fn , int ln )
00158 {
00159 int jj ;
00160 mallitem * ip ;
00161
00162 if( fred == NULL ) return ;
00163
00164 jj = mallkey((char *)fred) % SLOTS ;
00165 ip = find_empty_slot(jj) ;
00166
00167
00168
00169 ip->pmt = fred ;
00170 ip->psz = n ;
00171 ip->pfn = fn ;
00172 ip->pln = ln ;
00173 ip->pss = ++serial ;
00174
00175 ADD_TRACEBACK(ip) ;
00176
00177 return ;
00178 }
00179
00180
00181
00182
00183
00184 static void * malloc_track( size_t n , char * fn , int ln )
00185 {
00186 char * fred ;
00187 size_t nn = n + 2*NEXTRA ;
00188 int ii ;
00189
00190 fred = (char *) malloc(nn) ;
00191 if( fred == NULL ){
00192 fprintf(stderr,
00193 "\n*** MCW_malloc(%d) from %s#%d FAILS!\a\n",
00194 (int)n , fn , ln ) ;
00195 return NULL ;
00196 }
00197
00198
00199
00200 for( ii=0 ; ii < NEXTRA ; ii++ )
00201 fred[ii] = fred[n+NEXTRA+ii] = MAGIC ;
00202
00203 add_tracker(fred,n,fn,ln) ;
00204 return (void *)(fred+NEXTRA) ;
00205 }
00206
00207
00208
00209
00210
00211 static const char *pr_nam = NULL ;
00212 static int pr_lin = 0 ;
00213
00214 static void probe_track( mallitem * ip )
00215 {
00216 int ii ;
00217 size_t n ;
00218 char * fred ;
00219
00220 if( ip == NULL ){ pr_nam=NULL; return; }
00221 fred = (char *) ip->pmt ; if( fred == NULL ){ pr_nam=NULL; return; }
00222 n = ip->psz ;
00223
00224 for( ii=0 ; ii < NEXTRA ; ii++ )
00225 if( fred[ii] != MAGIC ){
00226 fprintf(stderr,"*** MCW_malloc pre-corruption! "
00227 "serial=%u size=%d source=%s line#%d",
00228 ip->pss,(int)ip->psz,ip->pfn,ip->pln ) ;
00229 #ifdef USE_TRACING
00230 { int tt ;
00231 for( tt=0 ; tt < NTB && ip->ptb[tt] != NULL ; tt++ )
00232 fprintf(stderr," <- %s",ip->ptb[tt]) ;
00233 }
00234 #endif
00235 fprintf(stderr,"\n") ;
00236
00237 if( pr_nam != NULL )
00238 fprintf(stderr," [[ Called from source=%.50s line#%d ]]\n",pr_nam,pr_lin);
00239 break ;
00240 }
00241
00242 for( ii=0 ; ii < NEXTRA ; ii++ )
00243 if( fred[n+NEXTRA+ii] != MAGIC ){
00244 fprintf(stderr,"*** MCW_malloc post-corruption! "
00245 "serial=%u size=%d source=%s line#%d\n",
00246 ip->pss,(int)ip->psz,ip->pfn,ip->pln ) ;
00247 #ifdef USE_TRACING
00248 { int tt ;
00249 for( tt=0 ; tt < NTB && ip->ptb[tt] != NULL ; tt++ )
00250 fprintf(stderr," <- %s",ip->ptb[tt]) ;
00251 }
00252 #endif
00253 fprintf(stderr,"\n") ;
00254
00255 if( pr_nam != NULL )
00256 fprintf(stderr," [[ Called from source=%.50s line#%d ]]\n",pr_nam,pr_lin);
00257 break ;
00258 }
00259
00260 pr_nam = NULL ;
00261 return ;
00262 }
00263
00264
00265
00266
00267
00268 static void * realloc_track( mallitem * ip, size_t n, char * fn, int ln )
00269 {
00270 char * nfred , * cfred ;
00271 size_t nn = n + 2*NEXTRA ;
00272 int ii , cjj,njj , kk ;
00273
00274 if( ip == NULL ) return NULL ;
00275
00276 pr_nam = (const char *)fn ; pr_lin = ln ;
00277 probe_track(ip) ;
00278 cfred = ip->pmt ;
00279
00280 nfred = (char*)realloc( cfred , nn ) ;
00281 if( nfred == NULL ){
00282 fprintf(stderr,
00283 "\n*** MCW_realloc(%d) from %s#%d FAILS!\a\n",
00284 (int)n , fn , ln ) ;
00285 return NULL ;
00286 }
00287
00288 for( ii=0 ; ii < NEXTRA ; ii++ )
00289 nfred[ii] = nfred[n+NEXTRA+ii] = MAGIC ;
00290
00291 cjj = mallkey(cfred) % SLOTS ;
00292 njj = mallkey(nfred) % SLOTS ;
00293
00294 if( cjj == njj ){
00295
00296 ip->pmt = nfred ;
00297 ip->psz = n ;
00298 ip->pfn = fn ;
00299 ip->pln = ln ;
00300 ip->pss = ++serial ;
00301
00302 ADD_TRACEBACK(ip) ;
00303
00304 } else {
00305
00306 add_tracker( nfred , n , fn , ln ) ;
00307
00308 ip->pmt = NULL ;
00309 }
00310
00311 return (void *)(nfred+NEXTRA) ;
00312 }
00313
00314
00315
00316
00317
00318 static void * calloc_track( size_t n , size_t m , char * fn , int ln )
00319 {
00320 void * fred ;
00321 size_t nn = n*m ;
00322
00323 fred = malloc_track(nn,fn,ln) ; if( fred == NULL ) return NULL ;
00324 memset( fred , 0 , nn ) ;
00325 return fred ;
00326 }
00327
00328
00329
00330
00331
00332 static void free_track( mallitem * ip )
00333 {
00334 char * cfred ;
00335
00336 if( ip == NULL ) return ;
00337 cfred = (char *) ip->pmt ;
00338 if( cfred == NULL ) return ;
00339
00340 pr_nam = NULL ;
00341 probe_track(ip) ;
00342
00343 free(cfred) ; ip->pmt = NULL ; return ;
00344 }
00345
00346
00347
00348
00349
00350 static int use_tracking = 0 ;
00351
00352 char * mcw_malloc_status(const char *fn , int ln)
00353 {
00354 static char buf[128] = "\0" ;
00355 int jj,kk , nptr=0 ; size_t nbyt=0 ;
00356
00357 if( ! use_tracking ) return NULL ;
00358
00359 for( jj=0 ; jj < SLOTS ; jj++ ){
00360 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
00361 if( htab[jj][kk].pmt != NULL ){
00362 pr_nam = (const char *)fn ; pr_lin = ln ;
00363 probe_track( htab[jj]+kk ) ;
00364 nptr++ ; nbyt += htab[jj][kk].psz ;
00365 }
00366 }
00367 }
00368
00369 sprintf(buf,"chunks=%d bytes=%u",nptr,(UINT)nbyt) ;
00370 return buf ;
00371 }
00372
00373
00374
00375
00376
00377 extern int THD_is_file( char * ) ;
00378 extern void qsort_intint( int , int * , int * ) ;
00379
00380 void mcw_malloc_dump(void)
00381 {
00382 int ii,jj,kk ;
00383 char fname[32] , * str ;
00384 FILE * fp = NULL ;
00385 int nptr=0 ;
00386 int * ss , * jk ;
00387
00388 if( ! use_tracking ) return ;
00389
00390
00391
00392 for( ii=1 ; ii < 1000 ; ii++ ){
00393 sprintf(fname,"malldump.%03d",ii) ;
00394 if( THD_is_file(fname) ) continue ;
00395 fp = fopen( fname , "w" ) ;
00396 if( fp == NULL ){
00397 fprintf(stderr,"** Unable to open file %s for malloc table dump!\n",
00398 fname ) ;
00399 return ;
00400 }
00401 break ;
00402 }
00403
00404 if( fp == NULL ){
00405 fprintf(stderr,"** Attempt to exceed 999 malloc table dump files!\n") ;
00406 return ;
00407 }
00408
00409
00410
00411 for( jj=0 ; jj < SLOTS ; jj++ ){
00412 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
00413 if( htab[jj][kk].pmt != NULL ) nptr++ ;
00414 }
00415 }
00416
00417 if( nptr < 1 ){
00418 fprintf(fp ,"--- Nothing is malloc()-ed !? ---\n") ;
00419 fprintf(stderr,"--- Nothing is malloc()-ed !? ---\n") ;
00420 fclose(fp) ;
00421 }
00422
00423
00424
00425 ss = (int *) malloc(sizeof(int)*nptr) ;
00426 jk = (int *) malloc(sizeof(int)*nptr) ;
00427
00428 #define JBASE 32768
00429
00430
00431
00432 for( ii=jj=0 ; jj < SLOTS ; jj++ ){
00433 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
00434 if( htab[jj][kk].pmt != NULL ){
00435 ss[ii] = htab[jj][kk].pss ;
00436 jk[ii] = JBASE*jj + kk ;
00437 ii++ ;
00438 }
00439 }
00440 }
00441
00442 qsort_intint( nptr , ss , jk ) ;
00443
00444
00445
00446 #ifdef USE_TRACING
00447 fprintf(fp, "MCW Malloc Table Dump:\n"
00448 "serial# size source file line# address hash(j,k) <- Called by\n"
00449 "------- ---------- -------------------- ----- ---------- ----- --- ---------\n");
00450 #else
00451 fprintf(fp, "MCW Malloc Table Dump:\n"
00452 "serial# size source file line# address hash(j,k)\n"
00453 "------- ---------- -------------------- ----- ---------- ----- ---\n") ;
00454 #endif
00455
00456 for( ii=0 ; ii < nptr ; ii++ ){
00457 jj = jk[ii] / JBASE ;
00458 kk = jk[ii] % JBASE ;
00459 if( htab[jj][kk].pmt != NULL ){
00460 fprintf(fp,"%7u %10d %-20.30s %5d %10p %5d %3d",
00461 htab[jj][kk].pss , (int)htab[jj][kk].psz ,
00462 htab[jj][kk].pfn , htab[jj][kk].pln , htab[jj][kk].pmt ,
00463 jj,kk ) ;
00464 #ifdef USE_TRACING
00465 { int tt ;
00466 for( tt=0 ; tt < NTB && htab[jj][kk].ptb[tt] != NULL ; tt++ )
00467 fprintf(fp," <- %s",htab[jj][kk].ptb[tt]) ;
00468 }
00469 #endif
00470 fprintf(fp,"\n") ;
00471 }
00472 else
00473 fprintf(fp,"*** Error at ii=%d jj=%d kk=%d\n",ii,jj,kk) ;
00474 }
00475
00476 free(ss) ; free(jk) ;
00477
00478
00479
00480 str = mcw_malloc_status(NULL,0) ;
00481 fprintf(fp,"----- Summary: %s\n",str) ;
00482 fclose(fp) ;
00483
00484 fprintf(stderr,"** Malloc table dumped to file %s\n",fname) ;
00485 fprintf(stderr,"** Summary: %s\n",str) ;
00486
00487 return ;
00488 }
00489
00490
00491
00492
00493
00494 void enable_mcw_malloc()
00495 {
00496 char * str = getenv("AFNI_NO_MCW_MALLOC") ;
00497
00498 if( use_tracking ) return ;
00499
00500 use_tracking = 1 ;
00501 if( str!=NULL && ( str[0]=='y' || str[0]=='Y') ) use_tracking = 0 ;
00502
00503 if( use_tracking && htab == NULL ){
00504 int jj ;
00505 htab = (mallitem **) malloc( SLOTS * sizeof(mallitem *) ) ;
00506 nhtab = (int *) malloc( SLOTS * sizeof(int) ) ;
00507 for( jj=0 ; jj < SLOTS ; jj++ ){
00508 htab[jj] = NULL ; nhtab[jj] = 0 ;
00509 }
00510 }
00511
00512 return ;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522 static int pz = 0;
00523 void pause_mcw_malloc()
00524 {
00525 if (pz) return;
00526 if (use_tracking) {
00527 pz = 1;
00528 use_tracking = 0;
00529 }
00530 return;
00531 }
00532 void resume_mcw_malloc()
00533 {
00534 if (!pz) return;
00535 pz = 0;
00536 use_tracking = 1;
00537 return;
00538 }
00539 int mcw_malloc_paused()
00540 {
00541 return(pz);
00542 }
00543
00544
00545
00546
00547 int mcw_malloc_enabled(){ return (use_tracking != 0) ; }
00548
00549
00550
00551
00552
00553 void * mcw_malloc( size_t n , char * fnam , int lnum )
00554 {
00555 if( use_tracking ) return malloc_track(n,fnam,lnum) ;
00556 else return malloc(n) ;
00557 }
00558
00559
00560
00561
00562
00563 void * mcw_realloc( void * fred , size_t n , char * fnam , int lnum )
00564 {
00565 mallitem * ip ;
00566
00567 if( fred == NULL )
00568 return mcw_malloc( n , fnam , lnum ) ;
00569
00570 if( use_tracking && (ip=shift_tracker(fred)) != NULL )
00571 return realloc_track( ip , n , fnam,lnum ) ;
00572 else
00573 return realloc( fred , n ) ;
00574 }
00575
00576
00577
00578
00579
00580 void * mcw_calloc( size_t n , size_t m , char * fnam , int lnum )
00581 {
00582 if( use_tracking ) return calloc_track( n , m , fnam,lnum ) ;
00583 else return calloc( n , m ) ;
00584 }
00585
00586
00587
00588
00589
00590 void mcw_free( void * fred )
00591 {
00592 mallitem * ip ;
00593
00594 if( fred == NULL ) return ;
00595
00596 if( use_tracking && (ip=shift_tracker(fred)) != NULL ) free_track( ip ) ;
00597 else free( fred ) ;
00598 }
00599
00600
00601
00602
00603
00604 char * mcw_XtMalloc( Cardinal n , char * fnam , int lnum )
00605 {
00606 if( use_tracking ) return (char *) malloc_track(n,fnam,lnum) ;
00607 else return (char *)XtMalloc(n) ;
00608 }
00609
00610
00611
00612
00613
00614 char * mcw_XtRealloc( char *p, Cardinal n , char * fnam , int lnum )
00615 {
00616 mallitem * ip ;
00617
00618 if( p == NULL )
00619 return mcw_XtMalloc( n , fnam , lnum ) ;
00620
00621 if( use_tracking && (ip=shift_tracker(p)) != NULL )
00622 return (char*)realloc_track( ip , n , fnam,lnum ) ;
00623 else
00624 return (char*)XtRealloc( p , n ) ;
00625 }
00626
00627
00628
00629
00630
00631 void mcw_XtFree( char *p )
00632 {
00633 mallitem * ip ;
00634
00635 if( p == NULL ) return ;
00636
00637 if( use_tracking && (ip=shift_tracker(p)) != NULL ) free_track(ip) ;
00638 else XtFree(p) ;
00639 }
00640
00641
00642
00643
00644
00645 char * mcw_XtCalloc( Cardinal n , Cardinal m , char * fnam , int lnum )
00646 {
00647 if( use_tracking ) return (char *) calloc_track( n , m , fnam,lnum ) ;
00648 else return XtCalloc( n , m ) ;
00649 }