papi_memory.c File Reference

Include dependency graph for papi_memory.c:

Go to the source code of this file.

Defines

#define IN_MEM_FILE
#define MEM_PROLOG   (2*sizeof(void *))
#define MEM_EPILOG   4
#define MEM_EPILOG_1   0xC
#define MEM_EPILOG_2   0xA
#define MEM_EPILOG_3   0xC
#define MEM_EPILOG_4   0xA

Functions

static pmem_tget_mem_ptr (void *ptr)
static pmem_tinit_mem_ptr (void *, int, char *, int)
static void insert_mem_ptr (pmem_t *)
static void remove_mem_ptr (pmem_t *)
static int set_epilog (pmem_t *mem_ptr)
void * _papi_realloc (char *file, int line, void *ptr, size_t size)
void * _papi_calloc (char *file, int line, size_t nmemb, size_t size)
void * _papi_malloc (char *file, int line, size_t size)
char * _papi_strdup (char *file, int line, const char *s)
int _papi_valid_free (char *file, int line, void *ptr)
void _papi_free (char *file, int line, void *ptr)
void _papi_mem_print_info (void *ptr)
void _papi_mem_print_stats ()
int _papi_mem_overhead (int type)
void _papi_mem_cleanup_all ()
static int _papi_mem_check_buf_overflow (pmem_t *tmp)
int _papi_mem_check_all_overflow ()

Variables

static pmem_tmem_head = NULL

Detailed Description

Author:
Kevin London london@cs.utk.edu PAPI memory allocation provides for checking and maintenance of all memory allocated through this interface. Implemented as a series of wrappers around standard C memory allocation routines, _papi_malloc and associated functions add a prolog and optional epilog to each malloc'd pointer. The prolog, sized to preserve memory alignment, contains a pointer to a linked list of pmem_t structures that describe every block of memory allocated through these calls. The optional epilog is enabled if DEBUG is defined, and contains a distinctive pattern that allows checking for pointer overflow.

Definition in file papi_memory.c.


Define Documentation

#define IN_MEM_FILE

Definition at line 16 of file papi_memory.c.

#define MEM_EPILOG   4

Define the amount of extra memory at the end of the alloc'd pointer. Also define the contents: 0xCACA

Definition at line 38 of file papi_memory.c.

#define MEM_EPILOG_1   0xC

Definition at line 39 of file papi_memory.c.

#define MEM_EPILOG_2   0xA

Definition at line 40 of file papi_memory.c.

#define MEM_EPILOG_3   0xC

Definition at line 41 of file papi_memory.c.

#define MEM_EPILOG_4   0xA

Definition at line 42 of file papi_memory.c.

#define MEM_PROLOG   (2*sizeof(void *))

Define the amount of extra memory at the beginning of the alloc'd pointer. This is usually the size of a pointer, but in some cases needs to be bigger to preserve data alignment.

Definition at line 31 of file papi_memory.c.


Function Documentation

void* _papi_calloc ( char *  file,
int  line,
size_t  nmemb,
size_t  size 
)

Definition at line 113 of file papi_memory.c.

00114 {
00115     void *ptr = _papi_malloc( file, line, size * nmemb );
00116 
00117     if ( !ptr )
00118         return ( NULL );
00119     memset( ptr, 0, size * nmemb );
00120     return ( ptr );
00121 }

Here is the call graph for this function:

void _papi_free ( char *  file,
int  line,
void *  ptr 
)

Frees up the ptr

Definition at line 226 of file papi_memory.c.

00227 {
00228     pmem_t *mem_ptr = get_mem_ptr( ptr );
00229 
00230     if ( !mem_ptr ) {
00231         ( void ) file;
00232         ( void ) line;
00233         return;
00234     }
00235 
00236     MEMDBG( "%p: Freeing %d bytes from File: %s  Line: %d\n", mem_ptr->ptr,
00237             mem_ptr->size, file, line );
00238 
00239     _papi_hwi_lock( MEMORY_LOCK );
00240     remove_mem_ptr( mem_ptr );
00241     _papi_mem_check_all_overflow(  );
00242     _papi_hwi_unlock( MEMORY_LOCK );
00243 }

Here is the call graph for this function:

void* _papi_malloc ( char *  file,
int  line,
size_t  size 
)

Definition at line 124 of file papi_memory.c.

00125 {
00126     void *ptr;
00127     void **tmp;
00128     pmem_t *mem_ptr;
00129     size_t nsize = size + MEM_PROLOG;
00130 
00131 #ifdef DEBUG
00132     nsize += MEM_EPILOG;
00133 #endif
00134 
00135     if ( size == 0 ) {
00136         MEMDBG( "Attempting to allocate %lu bytes from File: %s  Line: %d\n",
00137                 ( unsigned long ) size, file, line );
00138         return ( NULL );
00139     }
00140 
00141     ptr = ( void * ) malloc( nsize );
00142 
00143     if ( !ptr )
00144         return ( NULL );
00145     else {
00146         if ( ( mem_ptr =
00147                init_mem_ptr( ( char * ) ptr + MEM_PROLOG, ( int ) size, file,
00148                              line ) ) == NULL ) {
00149             free( ptr );
00150             return ( NULL );
00151         }
00152         tmp = ptr;
00153         *tmp = mem_ptr;
00154         ptr = mem_ptr->ptr;
00155         mem_ptr->ptr = ptr;
00156         _papi_hwi_lock( MEMORY_LOCK );
00157         insert_mem_ptr( mem_ptr );
00158         set_epilog( mem_ptr );
00159         _papi_hwi_unlock( MEMORY_LOCK );
00160 
00161         MEMDBG( "%p: Allocated %lu bytes from File: %s  Line: %d\n",
00162                 mem_ptr->ptr, ( unsigned long ) size, file, line );
00163         return ( ptr );
00164     }
00165     return ( NULL );
00166 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_mem_check_all_overflow (  ) 

Definition at line 470 of file papi_memory.c.

00471 {
00472     int fnd = 0;
00473 #ifdef DEBUG
00474     pmem_t *tmp;
00475 
00476     for ( tmp = mem_head; tmp; tmp = tmp->next ) {
00477         if ( _papi_mem_check_buf_overflow( tmp ) )
00478             fnd++;
00479     }
00480 
00481     if ( fnd ) {
00482         LEAKDBG( "%d Total Buffer overflows detected!\n", fnd );
00483     }
00484 #endif
00485     return ( fnd );
00486 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int _papi_mem_check_buf_overflow ( pmem_t tmp  )  [static]

Definition at line 438 of file papi_memory.c.

00439 {
00440     int fnd = 0;
00441     char *ptr;
00442     char *tptr;
00443 
00444     if ( !tmp )
00445         return ( 0 );
00446 
00447     tptr = tmp->ptr;
00448     tptr += tmp->size;
00449 
00450     /* Move to the buffer overflow padding */
00451     ptr = ( ( char * ) tmp->ptr ) + tmp->size;
00452     if ( *ptr++ != MEM_EPILOG_1 )
00453         fnd = 1;
00454     else if ( *ptr++ != MEM_EPILOG_2 )
00455         fnd = 2;
00456     else if ( *ptr++ != MEM_EPILOG_3 )
00457         fnd = 3;
00458     else if ( *ptr++ != MEM_EPILOG_4 )
00459         fnd = 4;
00460 
00461     if ( fnd ) {
00462         LEAKDBG( "Buffer Overflow[%d] for %p allocated from %s at line %d\n",
00463                  fnd, tmp->ptr, tmp->file, tmp->line );
00464     }
00465     return ( fnd );
00466 }

Here is the caller graph for this function:

void _papi_mem_cleanup_all (  ) 

Clean all memory up and print out memory leak information to stderr

Definition at line 303 of file papi_memory.c.

00304 {
00305     pmem_t *ptr = NULL, *tmp = NULL;
00306 #ifdef DEBUG
00307     int cnt = 0;
00308 #endif
00309 
00310     _papi_hwi_lock( MEMORY_LOCK );
00311     _papi_mem_check_all_overflow(  );
00312 
00313     for ( ptr = mem_head; ptr; ptr = tmp ) {
00314         tmp = ptr->next;
00315 #ifdef DEBUG
00316         LEAKDBG( "MEMORY LEAK: %p of %d bytes, from File: %s Line: %d\n",
00317                  ptr->ptr, ptr->size, ptr->file, ptr->line );
00318         cnt += ptr->size;
00319 #endif
00320 
00321         remove_mem_ptr( ptr );
00322     }
00323     _papi_hwi_unlock( MEMORY_LOCK );
00324 #ifdef DEBUG
00325     if ( 0 != cnt ) { 
00326         LEAKDBG( "TOTAL MEMORY LEAK: %d bytes.\n", cnt );
00327     }
00328 #endif
00329 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_mem_overhead ( int  type  ) 

Return the amount of memory overhead of the PAPI library and the memory system PAPI_MEM_LIB_OVERHEAD is the library overhead PAPI_MEM_OVERHEAD is the memory overhead They both can be | together This only includes "malloc'd memory"

Definition at line 280 of file papi_memory.c.

00281 {
00282     pmem_t *ptr = NULL;
00283     int size = 0;
00284 
00285     _papi_hwi_lock( MEMORY_LOCK );
00286     for ( ptr = mem_head; ptr; ptr = ptr->next ) {
00287         if ( type & PAPI_MEM_LIB_OVERHEAD )
00288             size += ptr->size;
00289         if ( type & PAPI_MEM_OVERHEAD ) {
00290             size += ( int ) sizeof ( pmem_t );
00291             size += ( int ) MEM_PROLOG;
00292 #ifdef DEBUG
00293             size += ( int ) MEM_EPILOG;
00294 #endif
00295         }
00296     }
00297     _papi_hwi_unlock( MEMORY_LOCK );
00298     return size;
00299 }

Here is the call graph for this function:

void _papi_mem_print_info ( void *  ptr  ) 

Print information about the memory including file and location it came from

Definition at line 247 of file papi_memory.c.

00248 {
00249     pmem_t *mem_ptr = get_mem_ptr( ptr );
00250 
00251 #ifdef DEBUG
00252     fprintf( stderr, "%p: Allocated %d bytes from File: %s  Line: %d\n", ptr,
00253              mem_ptr->size, mem_ptr->file, mem_ptr->line );
00254 #else
00255     fprintf( stderr, "%p: Allocated %d bytes\n", ptr, mem_ptr->size );
00256 #endif
00257     return;
00258 }

Here is the call graph for this function:

Here is the caller graph for this function:

void _papi_mem_print_stats (  ) 

Print out all memory information

Definition at line 262 of file papi_memory.c.

00263 {
00264     pmem_t *tmp = NULL;
00265 
00266     _papi_hwi_lock( MEMORY_LOCK );
00267     for ( tmp = mem_head; tmp; tmp = tmp->next ) {
00268         _papi_mem_print_info( tmp->ptr );
00269     }
00270     _papi_hwi_unlock( MEMORY_LOCK );
00271 }

Here is the call graph for this function:

void* _papi_realloc ( char *  file,
int  line,
void *  ptr,
size_t  size 
)

_papi_realloc -- given a pointer returned by _papi_malloc, returns a pointer to the related pmem_t structure describing this pointer. Checks for NULL pointers and returns NULL if error.

Definition at line 77 of file papi_memory.c.

00078 {
00079     size_t nsize = size + MEM_PROLOG;
00080     pmem_t *mem_ptr;
00081     void *nptr;
00082 
00083 #ifdef DEBUG
00084     nsize += MEM_EPILOG;
00085     _papi_hwi_lock( MEMORY_LOCK );
00086     _papi_mem_check_all_overflow(  );
00087 #endif
00088 
00089     if ( !ptr )
00090         return ( _papi_malloc( file, line, size ) );
00091 
00092     mem_ptr = get_mem_ptr( ptr );
00093     nptr = ( pmem_t * ) realloc( ( ( char * ) ptr - MEM_PROLOG ), nsize );
00094 
00095     if ( !nptr )
00096         return ( NULL );
00097 
00098     mem_ptr->size = ( int ) size;
00099     mem_ptr->ptr = ( char * ) nptr + MEM_PROLOG;
00100 #ifdef DEBUG
00101     strncpy( mem_ptr->file, file, DEBUG_FILE_LEN );
00102     mem_ptr->file[DEBUG_FILE_LEN - 1] = '\0';
00103     mem_ptr->line = line;
00104     set_epilog( mem_ptr );
00105     _papi_hwi_unlock( MEMORY_LOCK );
00106 #endif
00107     MEMDBG( "%p: Re-allocated: %lu bytes from File: %s  Line: %d\n",
00108             mem_ptr->ptr, ( unsigned long ) size, file, line );
00109     return ( mem_ptr->ptr );
00110 }

Here is the call graph for this function:

char* _papi_strdup ( char *  file,
int  line,
const char *  s 
)

Definition at line 169 of file papi_memory.c.

00170 {
00171     size_t size;
00172     char *ptr;
00173 
00174     if ( !s )
00175         return ( NULL );
00176 
00177     /* String Length +1 for \0 */
00178     size = strlen( s ) + 1;
00179     ptr = ( char * ) _papi_malloc( file, line, size );
00180 
00181     if ( !ptr )
00182         return ( NULL );
00183 
00184     memcpy( ptr, s, size );
00185     return ( ptr );
00186 }

Here is the call graph for this function:

int _papi_valid_free ( char *  file,
int  line,
void *  ptr 
)

Only frees the memory if PAPI malloced it returns 1 if pointer was valid; 0 if not

Definition at line 191 of file papi_memory.c.

00192 {
00193     pmem_t *tmp;
00194     int valid = 0;
00195 
00196     if ( !ptr ) {
00197         ( void ) file;
00198         ( void ) line;
00199         return ( 0 );
00200     }
00201 
00202     _papi_hwi_lock( MEMORY_LOCK );
00203 
00204     for ( tmp = mem_head; tmp; tmp = tmp->next ) {
00205         if ( ptr == tmp->ptr ) {
00206             pmem_t *mem_ptr = get_mem_ptr( ptr );
00207 
00208             if ( mem_ptr ) {
00209                 MEMDBG( "%p: Freeing %d bytes from File: %s  Line: %d\n",
00210                         mem_ptr->ptr, mem_ptr->size, file, line );
00211                 remove_mem_ptr( mem_ptr );
00212                 _papi_mem_check_all_overflow(  );
00213             }
00214 
00215             valid = 1;
00216             break;
00217         }
00218     }
00219 
00220     _papi_hwi_unlock( MEMORY_LOCK );
00221     return ( valid );
00222 }

Here is the call graph for this function:

static pmem_t * get_mem_ptr ( void *  ptr  )  [static]

Definition at line 344 of file papi_memory.c.

00345 {
00346     pmem_t **tmp_ptr = ( pmem_t ** ) ( ( char * ) ptr - MEM_PROLOG );
00347     pmem_t *mem_ptr;
00348 
00349     if ( !tmp_ptr || !ptr )
00350         return ( NULL );
00351 
00352     mem_ptr = *tmp_ptr;
00353     return ( mem_ptr );
00354 }

Here is the caller graph for this function:

pmem_t * init_mem_ptr ( void *  ptr,
int  size,
char *  file,
int  line 
) [static]

Definition at line 358 of file papi_memory.c.

00359 {
00360     pmem_t *mem_ptr = NULL;
00361     if ( ( mem_ptr = ( pmem_t * ) malloc( sizeof ( pmem_t ) ) ) == NULL )
00362         return ( NULL );
00363 
00364     mem_ptr->ptr = ptr;
00365     mem_ptr->size = size;
00366     mem_ptr->next = NULL;
00367     mem_ptr->prev = NULL;
00368 #ifdef DEBUG
00369     strncpy( mem_ptr->file, file, DEBUG_FILE_LEN );
00370     mem_ptr->file[DEBUG_FILE_LEN - 1] = '\0';
00371     mem_ptr->line = line;
00372 #else
00373     ( void ) file;           /*unused */
00374     ( void ) line;           /*unused */
00375 #endif
00376     return ( mem_ptr );
00377 }

Here is the caller graph for this function:

static void insert_mem_ptr ( pmem_t ptr  )  [static]

Definition at line 383 of file papi_memory.c.

00384 {
00385     if ( !ptr )
00386         return;
00387 
00388     if ( !mem_head ) {
00389         mem_head = ptr;
00390         ptr->next = NULL;
00391         ptr->prev = NULL;
00392     } else {
00393         mem_head->prev = ptr;
00394         ptr->next = mem_head;
00395         mem_head = ptr;
00396     }
00397     return;
00398 }

Here is the caller graph for this function:

static void remove_mem_ptr ( pmem_t ptr  )  [static]

Definition at line 405 of file papi_memory.c.

00406 {
00407     if ( !ptr )
00408         return;
00409 
00410     if ( ptr->prev )
00411         ptr->prev->next = ptr->next;
00412     if ( ptr->next )
00413         ptr->next->prev = ptr->prev;
00414     if ( ptr == mem_head )
00415         mem_head = ptr->next;
00416     free( ptr );
00417 }

Here is the caller graph for this function:

static int set_epilog ( pmem_t mem_ptr  )  [static]

Definition at line 420 of file papi_memory.c.

00421 {
00422 #ifdef DEBUG
00423     char *chptr = ( char * ) mem_ptr->ptr + mem_ptr->size;
00424     *chptr++ = MEM_EPILOG_1;
00425     *chptr++ = MEM_EPILOG_2;
00426     *chptr++ = MEM_EPILOG_3;
00427     *chptr++ = MEM_EPILOG_4;
00428     return ( _papi_mem_check_all_overflow(  ) );
00429 #else
00430     ( void ) mem_ptr;        /*unused */
00431 #endif
00432     return ( 0 );
00433 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

pmem_t* mem_head = NULL [static]

Definition at line 46 of file papi_memory.c.


Generated on 8 Sep 2016 for PAPI by  doxygen 1.6.1