2011-05-01 10:49:43 +04:00
/* $NetBSD: rf_debugMem.c,v 1.21 2011/05/01 06:49:43 mrg Exp $ */
1998-11-13 07:20:26 +03:00
/*
* Copyright ( c ) 1995 Carnegie - Mellon University .
* All rights reserved .
*
* Author : Daniel Stodolsky , Mark Holland , Jim Zelenka
*
* Permission to use , copy , modify and distribute this software and
* its documentation is hereby granted , provided that both the copyright
* notice and this permission notice appear in all copies of the
* software , derivative works or modified versions , and any portions
* thereof , and that both notices appear in supporting documentation .
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS " AS IS "
* CONDITION . CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE .
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software . Distribution @ CS . CMU . EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213 - 3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes .
*/
/* debugMem.c: memory usage debugging stuff.
1999-02-05 03:06:06 +03:00
* Malloc , Calloc , and Free are # defined everywhere
1998-11-13 07:20:26 +03:00
* to do_malloc , do_calloc , and do_free .
*/
2001-11-13 10:11:12 +03:00
# include <sys/cdefs.h>
2011-05-01 10:49:43 +04:00
__KERNEL_RCSID ( 0 , " $NetBSD: rf_debugMem.c,v 1.21 2011/05/01 06:49:43 mrg Exp $ " ) ;
2001-11-13 10:11:12 +03:00
2001-10-04 19:58:51 +04:00
# include <dev/raidframe/raidframevar.h>
1998-11-13 07:20:26 +03:00
# include "rf_threadstuff.h"
# include "rf_options.h"
# include "rf_debugMem.h"
# include "rf_general.h"
2011-05-01 10:49:43 +04:00
# include "rf_shutdown.h"
1998-11-13 07:20:26 +03:00
2002-09-17 03:40:57 +04:00
# if RF_DEBUG_MEM
1999-09-05 01:11:21 +04:00
static long tot_mem_in_use = 0 ;
1998-11-13 07:20:26 +03:00
/* Hash table of information about memory allocations */
# define RF_MH_TABLESIZE 1000
struct mh_struct {
1999-02-05 03:06:06 +03:00
void * address ;
int size ;
int line ;
2011-05-01 10:49:43 +04:00
const char * filen ;
1999-02-05 03:06:06 +03:00
char allocated ;
struct mh_struct * next ;
1998-11-13 07:20:26 +03:00
} ;
static struct mh_struct * mh_table [ RF_MH_TABLESIZE ] ;
2011-05-01 10:49:43 +04:00
static rf_declare_mutex2 ( rf_debug_mem_mutex ) ;
2002-09-17 03:40:57 +04:00
static int mh_table_initialized = 0 ;
1998-11-13 07:20:26 +03:00
2011-05-01 10:49:43 +04:00
static void memory_hash_insert ( void * addr , int size , int line , const char * filen ) ;
2002-09-17 03:40:57 +04:00
static int memory_hash_remove ( void * addr , int sz ) ;
1998-11-13 07:20:26 +03:00
2005-02-27 03:26:58 +03:00
void
2011-05-01 10:49:43 +04:00
rf_record_malloc ( void * p , int size , int line , const char * filen )
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
RF_ASSERT ( size ! = 0 ) ;
2011-05-01 10:49:43 +04:00
/* rf_lock_mutex2(rf_debug_mem_mutex); */
1999-02-05 03:06:06 +03:00
memory_hash_insert ( p , size , line , filen ) ;
tot_mem_in_use + = size ;
2011-05-01 10:49:43 +04:00
/* rf_unlock_mutex2(rf_debug_mem_mutex); */
1999-02-05 03:06:06 +03:00
if ( ( long ) p = = rf_memDebugAddress ) {
printf ( " Allocate: debug address allocated from line %d file %s \n " , line , filen ) ;
}
1998-11-13 07:20:26 +03:00
}
2005-02-27 03:26:58 +03:00
void
2003-12-31 00:59:03 +03:00
rf_unrecord_malloc ( void * p , int sz )
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
int size ;
2011-05-01 10:49:43 +04:00
/* rf_lock_mutex2(rf_debug_mem_mutex); */
1999-02-05 03:06:06 +03:00
size = memory_hash_remove ( p , sz ) ;
tot_mem_in_use - = size ;
2011-05-01 10:49:43 +04:00
/* rf_unlock_mutex2(rf_debug_mem_mutex); */
1999-02-05 03:06:06 +03:00
if ( ( long ) p = = rf_memDebugAddress ) {
printf ( " Free: Found debug address \n " ) ; /* this is really only a
* flag line for gdb */
}
1998-11-13 07:20:26 +03:00
}
2005-02-27 03:26:58 +03:00
void
2009-03-18 13:22:21 +03:00
rf_print_unfreed ( void )
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
int i , foundone = 0 ;
struct mh_struct * p ;
for ( i = 0 ; i < RF_MH_TABLESIZE ; i + + ) {
for ( p = mh_table [ i ] ; p ; p = p - > next )
if ( p - > allocated ) {
if ( ! foundone )
printf ( " \n \n There are unfreed memory locations at program shutdown: \n " ) ;
foundone = 1 ;
printf ( " Addr 0x%lx Size %d line %d file %s \n " ,
( long ) p - > address , p - > size , p - > line , p - > filen ) ;
}
}
if ( tot_mem_in_use ) {
printf ( " %ld total bytes in use \n " , tot_mem_in_use ) ;
}
1998-11-13 07:20:26 +03:00
}
2002-09-17 03:40:57 +04:00
# endif /* RF_DEBUG_MEM */
1998-11-13 07:20:26 +03:00
2011-05-01 10:49:43 +04:00
# if RF_DEBUG_MEM
static void
rf_ShutdownDebugMem ( void * unused )
{
rf_destroy_mutex2 ( rf_debug_mem_mutex ) ;
}
# endif
2005-02-27 03:26:58 +03:00
int
2006-11-16 04:32:37 +03:00
rf_ConfigureDebugMem ( RF_ShutdownList_t * * listp )
1998-11-13 07:20:26 +03:00
{
2002-09-17 03:40:57 +04:00
# if RF_DEBUG_MEM
2008-02-12 06:12:41 +03:00
int i ;
1998-11-13 07:20:26 +03:00
2011-05-01 10:49:43 +04:00
rf_init_mutex2 ( rf_debug_mem_mutex , IPL_VM ) ;
1999-02-05 03:06:06 +03:00
if ( rf_memDebug ) {
for ( i = 0 ; i < RF_MH_TABLESIZE ; i + + )
mh_table [ i ] = NULL ;
mh_table_initialized = 1 ;
}
2011-05-01 10:49:43 +04:00
rf_ShutdownCreate ( listp , rf_ShutdownDebugMem , NULL ) ;
2002-09-17 03:40:57 +04:00
# endif
1999-02-05 03:06:06 +03:00
return ( 0 ) ;
}
2002-09-17 03:40:57 +04:00
# if RF_DEBUG_MEM
1998-11-13 07:20:26 +03:00
# define HASHADDR(_a_) ( (((unsigned long) _a_)>>3) % RF_MH_TABLESIZE )
2005-02-27 03:26:58 +03:00
static void
2011-05-01 10:49:43 +04:00
memory_hash_insert ( void * addr , int size , int line , const char * filen )
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
unsigned long bucket = HASHADDR ( addr ) ;
struct mh_struct * p ;
RF_ASSERT ( mh_table_initialized ) ;
/* search for this address in the hash table */
for ( p = mh_table [ bucket ] ; p & & ( p - > address ! = addr ) ; p = p - > next ) ;
if ( ! p ) {
RF_Malloc ( p , sizeof ( struct mh_struct ) , ( struct mh_struct * ) ) ;
RF_ASSERT ( p ) ;
p - > next = mh_table [ bucket ] ;
mh_table [ bucket ] = p ;
p - > address = addr ;
p - > allocated = 0 ;
}
if ( p - > allocated ) {
printf ( " ERROR: reallocated address 0x%lx from line %d, file %s without intervening free \n " , ( long ) addr , line , filen ) ;
printf ( " last allocated from line %d file %s \n " , p - > line , p - > filen ) ;
RF_ASSERT ( 0 ) ;
}
p - > size = size ;
p - > line = line ;
p - > filen = filen ;
p - > allocated = 1 ;
1998-11-13 07:20:26 +03:00
}
2005-02-27 03:26:58 +03:00
static int
2003-12-31 00:59:03 +03:00
memory_hash_remove ( void * addr , int sz )
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
unsigned long bucket = HASHADDR ( addr ) ;
struct mh_struct * p ;
RF_ASSERT ( mh_table_initialized ) ;
for ( p = mh_table [ bucket ] ; p & & ( p - > address ! = addr ) ; p = p - > next ) ;
if ( ! p ) {
printf ( " ERROR: freeing never-allocated address 0x%lx \n " , ( long ) addr ) ;
RF_PANIC ( ) ;
}
if ( ! p - > allocated ) {
printf ( " ERROR: freeing unallocated address 0x%lx. Last allocation line %d file %s \n " , ( long ) addr , p - > line , p - > filen ) ;
RF_PANIC ( ) ;
}
if ( sz > 0 & & p - > size ! = sz ) { /* you can suppress this error by
* using a negative value as the size
* to free */
printf ( " ERROR: incorrect size at free for address 0x%lx: is %d should be %d. Alloc at line %d of file %s \n " , ( unsigned long ) addr , sz , p - > size , p - > line , p - > filen ) ;
RF_PANIC ( ) ;
}
p - > allocated = 0 ;
return ( p - > size ) ;
1998-11-13 07:20:26 +03:00
}
2002-09-17 03:40:57 +04:00
# endif /* RF_DEBUG_MEM */