PAPI 7.1.0.0
Loading...
Searching...
No Matches
papi_memory.c
Go to the documentation of this file.
1
16#define IN_MEM_FILE
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include "papi.h"
22#include "papi_lock.h"
23#include "papi_memory.h"
24#include "papi_internal.h"
25
26
31#define MEM_PROLOG (2*sizeof(void *))
32
33/* If you are tracing memory, then DEBUG must be set also. */
34#ifdef DEBUG
38#define MEM_EPILOG 4
39#define MEM_EPILOG_1 0xC
40#define MEM_EPILOG_2 0xA
41#define MEM_EPILOG_3 0xC
42#define MEM_EPILOG_4 0xA
43#endif
44
45/* Local global variables */
46static pmem_t *mem_head = NULL;
47
48/* Local Prototypes */
49static pmem_t *get_mem_ptr( void *ptr );
50static pmem_t *init_mem_ptr( void *, int, char *, int );
51static void insert_mem_ptr( pmem_t * );
52static void remove_mem_ptr( pmem_t * );
53static int set_epilog( pmem_t * mem_ptr );
54
55/**********************************************************************
56 * Exposed papi versions of std memory management routines: *
57 * _papi_realloc *
58 * _papi_calloc *
59 * _papi_malloc *
60 * _papi_strdup *
61 * _papi_free *
62 * _papi_valid_free *
63 * Exposed useful papi memory maintenance routines: *
64 * _papi_mem_print_info *
65 * _papi_mem_print_stats *
66 * _papi_mem_overhead *
67 * _papi_mem_cleanup_all *
68 * _papi_mem_check_buf_overflow *
69 * _papi_mem_check_all_overflow *
70 **********************************************************************/
71
76void *
77_papi_realloc( char *file, int line, void *ptr, size_t size )
78{
79 size_t nsize = size + MEM_PROLOG;
80 pmem_t *mem_ptr;
81 void *nptr;
82
83#ifdef DEBUG
84 nsize += MEM_EPILOG;
87#endif
88
89 if ( !ptr )
90 return ( _papi_malloc( file, line, size ) );
91
92 mem_ptr = get_mem_ptr( ptr );
93 nptr = ( pmem_t * ) realloc( ( ( char * ) ptr - MEM_PROLOG ), nsize );
94
95 if ( !nptr )
96 return ( NULL );
97
98 mem_ptr->size = ( int ) size;
99 mem_ptr->ptr = ( char * ) nptr + MEM_PROLOG;
100#ifdef DEBUG
101 strncpy( mem_ptr->file, file, DEBUG_FILE_LEN );
102 mem_ptr->file[DEBUG_FILE_LEN - 1] = '\0';
103 mem_ptr->line = line;
104 set_epilog( mem_ptr );
106#endif
107 MEMDBG( "%p: Re-allocated: %lu bytes from File: %s Line: %d\n",
108 mem_ptr->ptr, ( unsigned long ) size, file, line );
109 return ( mem_ptr->ptr );
110}
111
112void *
113_papi_calloc( char *file, int line, size_t nmemb, size_t size )
114{
115 void *ptr = _papi_malloc( file, line, size * nmemb );
116
117 if ( !ptr )
118 return ( NULL );
119 memset( ptr, 0, size * nmemb );
120 return ( ptr );
121}
122
123void *
124_papi_malloc( char *file, int line, size_t size )
125{
126 void *ptr;
127 void **tmp;
128 pmem_t *mem_ptr;
129 size_t nsize = size + MEM_PROLOG;
130
131#ifdef DEBUG
132 nsize += MEM_EPILOG;
133#endif
134
135 if ( size == 0 ) {
136 MEMDBG( "Attempting to allocate %lu bytes from File: %s Line: %d\n",
137 ( unsigned long ) size, file, line );
138 return ( NULL );
139 }
140
141 ptr = ( void * ) malloc( nsize );
142
143 if ( !ptr )
144 return ( NULL );
145 else {
146 if ( ( mem_ptr =
147 init_mem_ptr( ( char * ) ptr + MEM_PROLOG, ( int ) size, file,
148 line ) ) == NULL ) {
149 free( ptr );
150 return ( NULL );
151 }
152 tmp = ptr;
153 *tmp = mem_ptr;
154 ptr = mem_ptr->ptr;
155 mem_ptr->ptr = ptr;
157 insert_mem_ptr( mem_ptr );
158 set_epilog( mem_ptr );
160
161 MEMDBG( "%p: Allocated %lu bytes from File: %s Line: %d\n",
162 mem_ptr->ptr, ( unsigned long ) size, file, line );
163 return ( ptr );
164 }
165 return ( NULL );
166}
167
168char *
169_papi_strdup( char *file, int line, const char *s )
170{
171 size_t size;
172 char *ptr;
173
174 if ( !s )
175 return ( NULL );
176
177 /* String Length +1 for \0 */
178 size = strlen( s ) + 1;
179 ptr = ( char * ) _papi_malloc( file, line, size );
180
181 if ( !ptr )
182 return ( NULL );
183
184 memcpy( ptr, s, size );
185 return ( ptr );
186}
187
190int
191_papi_valid_free( char *file, int line, void *ptr )
192{
193 pmem_t *tmp;
194 int valid = 0;
195
196 if ( !ptr ) {
197 ( void ) file;
198 ( void ) line;
199 return ( 0 );
200 }
201
203
204 for ( tmp = mem_head; tmp; tmp = tmp->next ) {
205 if ( ptr == tmp->ptr ) {
206 pmem_t *mem_ptr = get_mem_ptr( ptr );
207
208 if ( mem_ptr ) {
209 MEMDBG( "%p: Freeing %d bytes from File: %s Line: %d\n",
210 mem_ptr->ptr, mem_ptr->size, file, line );
211 remove_mem_ptr( mem_ptr );
213 }
214
215 valid = 1;
216 break;
217 }
218 }
219
221 return ( valid );
222}
223
225void
226_papi_free( char *file, int line, void *ptr )
227{
228 pmem_t *mem_ptr = get_mem_ptr( ptr );
229
230 if ( !mem_ptr ) {
231 ( void ) file;
232 ( void ) line;
233 return;
234 }
235
236 MEMDBG( "%p: Freeing %d bytes from File: %s Line: %d\n", mem_ptr->ptr,
237 mem_ptr->size, file, line );
238
240 remove_mem_ptr( mem_ptr );
243}
244
246void
248{
249 pmem_t *mem_ptr = get_mem_ptr( ptr );
250
251#ifdef DEBUG
252 fprintf( stderr, "%p: Allocated %d bytes from File: %s Line: %d\n", ptr,
253 mem_ptr->size, mem_ptr->file, mem_ptr->line );
254#else
255 fprintf( stderr, "%p: Allocated %d bytes\n", ptr, mem_ptr->size );
256#endif
257 return;
258}
259
261void
263{
264 pmem_t *tmp = NULL;
265
267 for ( tmp = mem_head; tmp; tmp = tmp->next ) {
269 }
271}
272
279int
281{
282 pmem_t *ptr = NULL;
283 int size = 0;
284
286 for ( ptr = mem_head; ptr; ptr = ptr->next ) {
288 size += ptr->size;
289 if ( type & PAPI_MEM_OVERHEAD ) {
290 size += ( int ) sizeof ( pmem_t );
291 size += ( int ) MEM_PROLOG;
292#ifdef DEBUG
293 size += ( int ) MEM_EPILOG;
294#endif
295 }
296 }
298 return size;
299}
300
302void
304{
305 pmem_t *ptr = NULL, *tmp = NULL;
306#ifdef DEBUG
307 int cnt = 0;
308#endif
309
312
313 for ( ptr = mem_head; ptr; ptr = tmp ) {
314 tmp = ptr->next;
315#ifdef DEBUG
316 LEAKDBG( "MEMORY LEAK: %p of %d bytes, from File: %s Line: %d\n",
317 ptr->ptr, ptr->size, ptr->file, ptr->line );
318 cnt += ptr->size;
319#endif
320
321 remove_mem_ptr( ptr );
322 }
324#ifdef DEBUG
325 if ( 0 != cnt ) {
326 LEAKDBG( "TOTAL MEMORY LEAK: %d bytes.\n", cnt );
327 }
328#endif
329}
330
331/* Loop through memory structures and look for buffer overflows
332 * returns the number of overflows detected
333 */
334
335/**********************************************************************
336 * Private helper routines for papi memory management *
337 **********************************************************************/
338
339/* Given a pointer returned by _papi_malloc, returns a pointer
340 * to the related pmem_t structure describing this pointer.
341 * Checks for NULL pointers and returns NULL if error.
342 */
343static pmem_t *
344get_mem_ptr( void *ptr )
345{
346 pmem_t **tmp_ptr = ( pmem_t ** ) ( ( char * ) ptr - MEM_PROLOG );
347 pmem_t *mem_ptr;
348
349 if ( !tmp_ptr || !ptr )
350 return ( NULL );
351
352 mem_ptr = *tmp_ptr;
353 return ( mem_ptr );
354}
355
356/* Allocate and initialize a memory pointer */
357pmem_t *
358init_mem_ptr( void *ptr, int size, char *file, int line )
359{
360 pmem_t *mem_ptr = NULL;
361 if ( ( mem_ptr = ( pmem_t * ) malloc( sizeof ( pmem_t ) ) ) == NULL )
362 return ( NULL );
363
364 mem_ptr->ptr = ptr;
365 mem_ptr->size = size;
366 mem_ptr->next = NULL;
367 mem_ptr->prev = NULL;
368#ifdef DEBUG
369 strncpy( mem_ptr->file, file, DEBUG_FILE_LEN );
370 mem_ptr->file[DEBUG_FILE_LEN - 1] = '\0';
371 mem_ptr->line = line;
372#else
373 ( void ) file; /*unused */
374 ( void ) line; /*unused */
375#endif
376 return ( mem_ptr );
377}
378
379/* Insert the memory information
380 * Do not lock these routines, but lock in routines using these
381 */
382static void
384{
385 if ( !ptr )
386 return;
387
388 if ( !mem_head ) {
389 mem_head = ptr;
390 ptr->next = NULL;
391 ptr->prev = NULL;
392 } else {
393 mem_head->prev = ptr;
394 ptr->next = mem_head;
395 mem_head = ptr;
396 }
397 return;
398}
399
400/* Remove the memory information pointer and free the memory
401 * Do not using locking in this routine, instead lock around
402 * the sections of code that use this call.
403 */
404static void
406{
407 if ( !ptr )
408 return;
409
410 if ( ptr->prev )
411 ptr->prev->next = ptr->next;
412 if ( ptr->next )
413 ptr->next->prev = ptr->prev;
414 if ( ptr == mem_head )
415 mem_head = ptr->next;
416 free( ptr );
417}
418
419static int
420set_epilog( pmem_t * mem_ptr )
421{
422#ifdef DEBUG
423 char *chptr = ( char * ) mem_ptr->ptr + mem_ptr->size;
424 *chptr++ = MEM_EPILOG_1;
425 *chptr++ = MEM_EPILOG_2;
426 *chptr++ = MEM_EPILOG_3;
427 *chptr++ = MEM_EPILOG_4;
428 return ( _papi_mem_check_all_overflow( ) );
429#else
430 ( void ) mem_ptr; /*unused */
431#endif
432 return ( 0 );
433}
434
435/* Check for memory buffer overflows */
436#ifdef DEBUG
437static int
439{
440 int fnd = 0;
441 char *ptr;
442 char *tptr;
443
444 if ( !tmp )
445 return ( 0 );
446
447 tptr = tmp->ptr;
448 tptr += tmp->size;
449
450 /* Move to the buffer overflow padding */
451 ptr = ( ( char * ) tmp->ptr ) + tmp->size;
452 if ( *ptr++ != MEM_EPILOG_1 )
453 fnd = 1;
454 else if ( *ptr++ != MEM_EPILOG_2 )
455 fnd = 2;
456 else if ( *ptr++ != MEM_EPILOG_3 )
457 fnd = 3;
458 else if ( *ptr++ != MEM_EPILOG_4 )
459 fnd = 4;
460
461 if ( fnd ) {
462 LEAKDBG( "Buffer Overflow[%d] for %p allocated from %s at line %d\n",
463 fnd, tmp->ptr, tmp->file, tmp->line );
464 }
465 return ( fnd );
466}
467#endif
468
469int
471{
472 int fnd = 0;
473#ifdef DEBUG
474 pmem_t *tmp;
475
476 for ( tmp = mem_head; tmp; tmp = tmp->next ) {
478 fnd++;
479 }
480
481 if ( fnd ) {
482 LEAKDBG( "%d Total Buffer overflows detected!\n", fnd );
483 }
484#endif
485 return ( fnd );
486}
double tmp
double s
Definition: byte_profile.c:36
uint8_t valid
uint16_t type
Return codes and api definitions.
#define LEAKDBG(format, args...)
Definition: papi_debug.h:72
#define MEMDBG(format, args...)
Definition: papi_debug.h:71
FILE * stderr
#define MEMORY_LOCK
Definition: papi_internal.h:89
static pmem_t * get_mem_ptr(void *ptr)
Definition: papi_memory.c:344
int _papi_mem_overhead(int type)
Definition: papi_memory.c:280
#define MEM_EPILOG
Definition: papi_memory.c:38
void * _papi_realloc(char *file, int line, void *ptr, size_t size)
Definition: papi_memory.c:77
#define MEM_PROLOG
Definition: papi_memory.c:31
char * _papi_strdup(char *file, int line, const char *s)
Definition: papi_memory.c:169
void * _papi_calloc(char *file, int line, size_t nmemb, size_t size)
Definition: papi_memory.c:113
static void remove_mem_ptr(pmem_t *)
Definition: papi_memory.c:405
void _papi_mem_print_stats()
Definition: papi_memory.c:262
static pmem_t * init_mem_ptr(void *, int, char *, int)
Definition: papi_memory.c:358
static void insert_mem_ptr(pmem_t *)
Definition: papi_memory.c:383
#define MEM_EPILOG_1
Definition: papi_memory.c:39
void * _papi_malloc(char *file, int line, size_t size)
Definition: papi_memory.c:124
void _papi_mem_cleanup_all()
Definition: papi_memory.c:303
#define MEM_EPILOG_2
Definition: papi_memory.c:40
void _papi_free(char *file, int line, void *ptr)
Definition: papi_memory.c:226
static int set_epilog(pmem_t *mem_ptr)
Definition: papi_memory.c:420
int _papi_valid_free(char *file, int line, void *ptr)
Definition: papi_memory.c:191
#define MEM_EPILOG_3
Definition: papi_memory.c:41
static pmem_t * mem_head
Definition: papi_memory.c:46
static int _papi_mem_check_buf_overflow(pmem_t *tmp)
Definition: papi_memory.c:438
#define MEM_EPILOG_4
Definition: papi_memory.c:42
void _papi_mem_print_info(void *ptr)
Definition: papi_memory.c:247
int _papi_mem_check_all_overflow()
Definition: papi_memory.c:470
#define PAPI_MEM_OVERHEAD
Definition: papi_memory.h:61
#define DEBUG_FILE_LEN
Definition: papi_memory.h:6
#define PAPI_MEM_LIB_OVERHEAD
Definition: papi_memory.h:60
const char FILE * file
Definition: pscanf.h:13
int
Definition: sde_internal.h:89
char file[DEBUG_FILE_LEN]
Definition: papi_memory.h:13
void * ptr
Definition: papi_memory.h:10
int line
Definition: papi_memory.h:14
struct pmem * next
Definition: papi_memory.h:16
struct pmem * prev
Definition: papi_memory.h:17
int size
Definition: papi_memory.h:11
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:69
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:83