2002-11-23 05:44:14 +03:00
/* $NetBSD: rf_debugMem.c,v 1.12 2002/11/23 02:44:15 oster 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>
2002-11-23 05:44:14 +03:00
__KERNEL_RCSID ( 0 , " $NetBSD: rf_debugMem.c,v 1.12 2002/11/23 02:44:15 oster 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"
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 ;
char * filen ;
char allocated ;
struct mh_struct * next ;
1998-11-13 07:20:26 +03:00
} ;
static struct mh_struct * mh_table [ RF_MH_TABLESIZE ] ;
RF_DECLARE_MUTEX ( 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
2002-09-17 03:40:57 +04:00
static void memory_hash_insert ( void * addr , int size , int line , char * filen ) ;
static int memory_hash_remove ( void * addr , int sz ) ;
1998-11-13 07:20:26 +03:00
1999-02-05 03:06:06 +03:00
void
rf_record_malloc ( p , size , line , filen )
void * p ;
int size , line ;
char * filen ;
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
RF_ASSERT ( size ! = 0 ) ;
/* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
memory_hash_insert ( p , size , line , filen ) ;
tot_mem_in_use + = size ;
/* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
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
}
1999-02-05 03:06:06 +03:00
void
rf_unrecord_malloc ( p , sz )
void * p ;
int sz ;
1998-11-13 07:20:26 +03:00
{
1999-02-05 03:06:06 +03:00
int size ;
/* RF_LOCK_MUTEX(rf_debug_mem_mutex); */
size = memory_hash_remove ( p , sz ) ;
tot_mem_in_use - = size ;
/* RF_UNLOCK_MUTEX(rf_debug_mem_mutex); */
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
}
1999-02-05 03:06:06 +03:00
void
rf_print_unfreed ( )
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
1999-02-05 03:06:06 +03:00
int
rf_ConfigureDebugMem ( listp )
RF_ShutdownList_t * * listp ;
1998-11-13 07:20:26 +03:00
{
2002-09-17 03:40:57 +04:00
# if RF_DEBUG_MEM
1999-02-05 03:06:06 +03:00
int i , rc ;
1998-11-13 07:20:26 +03:00
1999-02-05 03:06:06 +03:00
rc = rf_create_managed_mutex ( listp , & rf_debug_mem_mutex ) ;
if ( rc ) {
2002-09-14 21:53:57 +04:00
rf_print_unable_to_init_mutex ( __FILE__ , __LINE__ , rc ) ;
1999-02-05 03:06:06 +03:00
return ( rc ) ;
}
if ( rf_memDebug ) {
for ( i = 0 ; i < RF_MH_TABLESIZE ; i + + )
mh_table [ i ] = NULL ;
mh_table_initialized = 1 ;
}
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 )
1999-02-05 03:06:06 +03:00
static void
memory_hash_insert ( addr , size , line , filen )
void * addr ;
int size , line ;
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
}
1999-02-05 03:06:06 +03:00
static int
memory_hash_remove ( addr , sz )
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 */