⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trmem.c

📁 fortran并行计算包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*  $Id: trmem.c,v 1.32 2007/02/22 21:56:13 gropp Exp $ * *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpiimpl.h"#include "trmem.h"#include <stdio.h>#include <string.h>#ifndef USE_MEMORY_TRACINGint MPIU_trvalid( const char str[] );#endif/* Temporary.  sig values will change *//* style: allow:malloc:3 sig:0 *//* style: allow:calloc:2 sig:0 *//* style: allow:free:3 sig:0 *//* style: allow:strdup:1 sig:0 *//* style: define:malloc:1 sig:0 *//* style: define:__strdup:1 sig:0 *//* style: define:FPRINTF:1 sig:0 */#ifdef malloc/* Undefine these in case they were set to 'error' */#undef malloc#undef calloc#undef free#undef strdup/* Some GNU implementations use __strdup for strdup */#if defined(__strdup)#define strdup(s) __strdup(s)#endif#endif#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)#include <stdlib.h>#else/* We should test to see if these will work */extern void *malloc( size_t );extern void *calloc( size_t, size_t );extern int free( void *);#endif#define FPRINTF fprintf/*D    MPIU_trspace - Routines for tracing space usage    Description:    MPIU_trmalloc replaces malloc and MPIU_trfree replaces free.      These routines    have the same syntax and semantics as the routines that they replace,    In addition, there are routines to report statistics on the memory    usage, and to report the currently allocated space.  These routines    are built on top of malloc and free, and can be used together with    them as long as any space allocated with MPIU_trmalloc is only freed with    MPIU_trfree.    Note that the malloced data is scrubbed each time; you don't get    random trash (or fortuitous zeros).  What you get is fc (bytes);    this will usually create a "bad" value.    As an aid in developing codes, a maximum memory threshold can     be set with MPIU_TrSetMaxMem. D*//* HEADER_DOUBLES is the number of doubles in a trSPACE header *//* We have to be careful about alignment rules here */#define USE_LONG_NAMES_IN_TRMEM#ifdef USE_LONG_NAMES_IN_TRMEM/* Assume worst case and align on 8 bytes */#define TR_ALIGN_BYTES 8#define TR_ALIGN_MASK  0x7#define TR_FNAME_LEN   48#define HEADER_DOUBLES 19#else#if SIZEOF_VOID_P > 4#define TR_ALIGN_BYTES 8#define TR_ALIGN_MASK  0x7#define TR_FNAME_LEN   16#define HEADER_DOUBLES 12#else#define TR_ALIGN_BYTES 4#define TR_ALIGN_MASK  0x3#define TR_FNAME_LEN   12#define HEADER_DOUBLES 8#endif#endif#define COOKIE_VALUE   0xf0e0d0c9#define ALREADY_FREED  0x0f0e0d9ctypedef struct TRSPACE {    unsigned long   size;    int             id;    int             lineno;    int             freed_lineno;    char            freed_fname[TR_FNAME_LEN];    char            fname[TR_FNAME_LEN];    struct TRSPACE *next, *prev;    unsigned long   cookie;        /* Cookie is always the last element 				      inorder to catch the off-by-one				      errors */    } TRSPACE;/* This union is used to insure that the block passed to the user is   aligned on a double boundary */typedef union TrSPACE {    TRSPACE sp;    double  v[HEADER_DOUBLES];    } TrSPACE;/* * This package maintains some state about itself.  These globals hold * this information. */static int     world_rank = -1;static long    allocated = 0, frags = 0;static TRSPACE *TRhead = 0;static int     TRid = 0;static int     TRidSet = 0;static int     TRlevel = 0;static unsigned char  TRDefaultByte = 0xda;#define MAX_TR_STACK 20static int     TRdebugLevel = 0;#define TR_MALLOC 0x1#define TR_FREE   0x2/* Used to keep track of allocations */static long    TRMaxMem = 0;static long    TRMaxMemId = 0;/* Used to limit allocation */static long    TRMaxMemAllow = 0;/* * Printing of addresses.   * * This is particularly difficult because there isn't a C integer type that is * known in advance to be the same size as an address, so we need some * way to convert a pointer into the characters the represent the address in  * hex.  We can't simply use %x or %lx since the size of an address might not * be an int or a long (e.g., it might be a long long). * * In order to handle this, we have our own routine to convert * an address to hex digits.  For thread safety, the character * string is allocated within the calling routine (rather than returning * a static string from the conversion routine). *//* 8 bytes = 16 hex chars + 0x (2 chars) + the null is 19 */#define MAX_ADDRESS_CHARS 19static void addrToHex( void *addr, char string[MAX_ADDRESS_CHARS] );/*+C   MPIU_trinit - Setup the space package.  Only needed for    error messages and flags.+*/void MPIU_trinit( int rank ){    char *s;    world_rank = rank;    /* FIXME: We should use generalized parameter handling here       to allow use of the command line as well as environment       variables */    s = getenv( "MPICH_TRMEM_VALIDATE" );    if (s && *s && (strcmp(s,"YES") == 0 || strcmp(s,"yes") == 0)) {	TRdebugLevel = 1;    }    s = getenv( "MPICH_TRMEM_INITZERO" );    if (s && *s && (strcmp(s,"YES") == 0 || strcmp(s,"yes") == 0)) {	TRDefaultByte = 0;    }    } /*+C    MPIU_trmalloc - Malloc with tracing    Input Parameters:+   a   - number of bytes to allocate.   lineno - line number where used.  Use __LINE__ for this-   fname  - file name where used.  Use __FILE__ for this    Returns:    double aligned pointer to requested storage, or null if not    available. +*/void *MPIU_trmalloc( unsigned int a, int lineno, const char fname[] ){    TRSPACE          *head;    char             *new;    unsigned long    *nend;    unsigned int     nsize;    int              l;    if (TRdebugLevel > 0) {	char buf[256];	MPIU_Snprintf( buf, 256, 		       "Invalid MALLOC arena detected at line %d in %s\n", 		       lineno, fname );	if (MPIU_trvalid( buf )) return 0;    }    nsize = a;    if (nsize & TR_ALIGN_MASK) 	nsize += (TR_ALIGN_BYTES - (nsize & TR_ALIGN_MASK));    if ((allocated + (long)nsize > TRMaxMemAllow) && TRMaxMemAllow) {	/* Return a null when memory would be exhausted */	/* This is only called when additional debugging is enabled,	   so the fact that this does not go through the regular error 	   message system is not a problem. */	MPIU_Error_printf( "Exceeded allowed memory! \n" );	return 0;    }    new = malloc( (unsigned)( nsize + sizeof(TrSPACE) + sizeof(unsigned long) ) );    if (!new) return 0;    memset( new, TRDefaultByte, 	    nsize + sizeof(TrSPACE) + sizeof(unsigned long) );    head = (TRSPACE *)new;    new  += sizeof(TrSPACE);    if (TRhead)	TRhead->prev = head;    head->next     = TRhead;    TRhead         = head;    head->prev     = 0;    head->size     = nsize;    head->id       = TRid;    head->lineno   = lineno;    if ((l = (int)strlen( fname )) > TR_FNAME_LEN-1 ) 	fname += (l - (TR_FNAME_LEN-1));    MPIU_Strncpy( head->fname, fname, TR_FNAME_LEN );    head->fname[TR_FNAME_LEN-1]= 0;    head->cookie   = COOKIE_VALUE;    nend           = (unsigned long *)(new + nsize);    nend[0]        = COOKIE_VALUE;    allocated += nsize;    if (allocated > TRMaxMem) {	TRMaxMem   = allocated;	TRMaxMemId = TRid;    }    frags     ++;    if (TRlevel & TR_MALLOC) {	/* Note that %08p (what we'd like to use) isn't accepted by	   all compilers */	MPIU_Error_printf( "[%d] Allocating %d bytes at %8p in %s:%d\n", 		     world_rank, a, new, fname, lineno );    }    return (void *)new;}/*+C   MPIU_trfree - Free with tracing   Input Parameters:+  a    - pointer to a block allocated with trmalloc.  line - line in file where called-  file - Name of file where called +*/void MPIU_trfree( void *a_ptr, int line, const char file[] ){    TRSPACE  *head;    char     *ahead;    char     *a = (char *)a_ptr;    unsigned long *nend;    int      l, nset;    char     hexstring[MAX_ADDRESS_CHARS];/* Don't try to handle empty blocks */    if (!a) return;    if (TRdebugLevel > 0) {	if (MPIU_trvalid( "Invalid MALLOC arena detected by FREE" )) return;    }    ahead = a;    a     = a - sizeof(TrSPACE);    head  = (TRSPACE *)a;    if (head->cookie != COOKIE_VALUE) {	/* Damaged header */	/* Note that %08p (what we'd like to use) isn't accepted by	   all compilers */	MPIU_Error_printf( 		     "[%d] Block at address %8p is corrupted; cannot free;\n\may be block not allocated with MPIU_trmalloc or MALLOC\n\called in %s at line %d\n", world_rank, a, file, line );	return;    }    nend = (unsigned long *)(ahead + head->size);/* Check that nend is properly aligned */    if ((sizeof(long) == 4 && ((long)nend & 0x3) != 0) ||	(sizeof(long) == 8 && ((long)nend & 0x7) != 0)) {	MPIU_Error_printf( "[%d] Block at address %lx is corrupted (invalid address or header)\n\called in %s at line %d\n", world_rank, (long)a + sizeof(TrSPACE), 		 file, line );	return;    }    if (*nend != COOKIE_VALUE) {	if (*nend == ALREADY_FREED) {	    addrToHex( (char *)a + sizeof(TrSPACE), hexstring );	    if (TRidSet) {		MPIU_Error_printf( 		     "[%d] Block [id=%d(%lu)] at address %s was already freed\n", 		     world_rank, head->id, head->size, hexstring );	    }	    else {		MPIU_Error_printf( 		     "[%d] Block at address %s was already freed\n", 		     world_rank, hexstring );	    }	    head->fname[TR_FNAME_LEN-1]	  = 0;  /* Just in case */	    head->freed_fname[TR_FNAME_LEN-1] = 0;  /* Just in case */	    MPIU_Error_printf(		     "[%d] Block freed in %s[%d]\n", world_rank, 		     head->freed_fname, head->freed_lineno );	    MPIU_Error_printf(		     "[%d] Block allocated at %s[%d]\n", 		     world_rank, head->fname, head->lineno );	    return;	}	else {	    /* Damaged tail */	    addrToHex( a, hexstring );	    if (TRidSet) {		MPIU_Error_printf(		     "[%d] Block [id=%d(%lu)] at address %s is corrupted (probably write past end)\n", 		     world_rank, head->id, head->size, hexstring );	    }	    else {		MPIU_Error_printf(		     "[%d] Block at address %s is corrupted (probably write past end)\n", 		     world_rank, hexstring );	    }	    head->fname[TR_FNAME_LEN-1]= 0;  /* Just in case */	    MPIU_Error_printf(		     "[%d] Block allocated in %s[%d]\n", world_rank, 		     head->fname, head->lineno );	}    }/* Mark the location freed */    *nend		   = ALREADY_FREED;    head->freed_lineno = line;    if ((l = (int)strlen( file )) > TR_FNAME_LEN-1 ) 	file += (l - (TR_FNAME_LEN-1));    MPIU_Strncpy( head->freed_fname, file, TR_FNAME_LEN );    allocated -= head->size;    frags     --;    if (head->prev)	head->prev->next = head->next;    else	TRhead = head->next;    if (head->next)	head->next->prev = head->prev;    if (TRlevel & TR_FREE) {	addrToHex( (char *)a + sizeof(TrSPACE), hexstring );	MPIU_Error_printf( "[%d] Freeing %lu bytes at %s in %s:%d\n", 		     world_rank, head->size, hexstring, file, line );    }        /*        Now, scrub the data (except possibly the first few ints) to       help catch access to already freed data      */    nset = head->size -  2 * sizeof(int);    if (nset > 0) 	memset( ahead + 2 * sizeof(int), TRDefaultByte, nset );    free( a );}/*+C   MPIU_trvalid - test the allocated blocks for validity.  This can be used to   check for memory overwrites.   Input Parameter:.  str - string to write out only if an error is detected.   Return value:   The number of errors detected.      Output Effect:   Error messages are written to stdout.  These have the form of either$   Block [id=%d(%d)] at address %lx is corrupted (probably write past end)$   Block allocated in <filename>[<linenumber>]   if the sentinal at the end of the block has been corrupted, and$   Block at address %lx is corrupted   if the sentinal at the begining of the block has been corrupted.   The address is the actual address of the block.  The id is the   value of TRID.   No output is generated if there are no problems detected.+*/int MPIU_trvalid( const char str[] ){    TRSPACE *head;    char    *a;    unsigned long *nend;    int     errs = 0;    char    hexstring[MAX_ADDRESS_CHARS];    head = TRhead;    while (head) {	if (head->cookie != COOKIE_VALUE) {	    if (!errs) MPIU_Error_printf( "%s\n", str );	    errs++;	    addrToHex( head, hexstring );	    MPIU_Error_printf( "[%d] Block at address %s is corrupted (invalid cookie in head)\n", 			 world_rank, hexstring );	    /* Must stop because if head is invalid, then the data in the	       head is probably also invalid, and using could lead to 	       SEGV or BUS  */	    return errs;	}	a    = (char *)(((TrSPACE*)head) + 1);	nend = (unsigned long *)(a + head->size);	if (nend[0] != COOKIE_VALUE) {	    if (!errs) MPIU_Error_printf( "%s\n", str );	    errs++;	    head->fname[TR_FNAME_LEN-1]= 0;  /* Just in case */	    addrToHex( a, hexstring );	    if (TRidSet) {		MPIU_Error_printf( 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -