Reduce code duplication among platforms, support hooking and unhooking (392009, r=dbaron).

git-svn-id: svn://10.0.0.236/trunk@236629 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
brendan%mozilla.org
2007-09-25 01:13:17 +00:00
parent 2a133d101d
commit 337a22147a
2 changed files with 217 additions and 446 deletions

View File

@@ -40,12 +40,10 @@
* ***** END LICENSE BLOCK ***** */
#ifdef NS_TRACE_MALLOC
/*
* TODO:
* - extend logfile so 'F' record tells free stack
* - diagnose rusty's SMP realloc oldsize corruption bug
* - #ifdef __linux__/x86 and port to other platforms
* - unify calltree with gc/boehm somehow (common utility lib?)
*/
* TODO:
* - FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=392008
* - extend logfile so 'F' record tells free stack
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -77,41 +75,43 @@
#define WRITE_FLAGS "w"
#define __libc_malloc(x) malloc(x)
#define __libc_calloc(x, y) calloc(x, y)
#define __libc_realloc(x, y) realloc(x, y)
#define __libc_free(x) free(x)
#elif defined(XP_UNIX)
#include <malloc.h>
#define WRITE_FLAGS "w"
#ifdef WRAP_SYSTEM_INCLUDES
#pragma GCC visibility push(default)
#endif
extern __ptr_t __libc_malloc(size_t);
extern __ptr_t __libc_calloc(size_t, size_t);
extern __ptr_t __libc_realloc(__ptr_t, size_t);
extern void __libc_free(__ptr_t);
extern __ptr_t __libc_memalign(size_t, size_t);
extern __ptr_t __libc_valloc(size_t);
#ifdef WRAP_SYSTEM_INCLUDES
#pragma GCC visibility pop
#endif
#elif defined(XP_WIN32)
#include <sys/timeb.h>/*for timeb*/
#include <sys/stat.h>/*for fstat*/
#include <sys/timeb.h> /* for timeb */
#include <sys/stat.h> /* for fstat */
#include <io.h> /*for write*/
#define WRITE_FLAGS "w"
#define __libc_malloc(x) dhw_orig_malloc(x)
#define __libc_calloc(x, y) dhw_orig_calloc(x,y)
#define __libc_realloc(x, y) dhw_orig_realloc(x,y)
#define __libc_free(x) dhw_orig_free(x)
#else /* not XP_MACOSX, XP_UNIX, or XP_WIN32 */
# error "Unknown build configuration!"
#endif
typedef struct logfile logfile;
@@ -144,11 +144,11 @@ static char *sdlogname = NULL; /* filename for shutdown leak log */
* This enables/disables trace-malloc logging.
*
* It is separate from suppress_tracing so that we do not have to pay
* the performance cost of repeated PR_GetThreadPrivate calls when
* the performance cost of repeated TM_TLS_GET_DATA calls when
* trace-malloc is disabled (which is not as bad as the locking we used
* to have).
*/
static int tracing_enabled = 1;
static uint32 tracing_enabled = 1;
/*
* This lock must be held while manipulating the calltree, the
@@ -575,7 +575,8 @@ static PLHashTable *filenames = NULL;
/* Table mapping method names to logged 'N' record serial numbers. */
static PLHashTable *methods = NULL;
static callsite *calltree(void **stack, size_t num_stack_entries)
static callsite *
calltree(void **stack, size_t num_stack_entries)
{
logfile *fp = logfp;
void *pc;
@@ -862,16 +863,17 @@ static callsite *calltree(void **stack, size_t num_stack_entries)
calltree_maxstack_top = site;
TM_EXIT_LOCK();
return site;
fail:
TM_EXIT_LOCK();
return NULL;
}
/* buffer the stack so that we can reverse it */
/*
* Buffer the stack from top at low index to bottom at high, so that we can
* reverse it in calltree.
*/
PR_STATIC_CALLBACK(void)
stack_callback(void *pc, void *closure)
{
@@ -889,7 +891,6 @@ stack_callback(void *pc, void *closure)
/*
* The caller MUST NOT be holding tmlock when calling backtrace.
*/
callsite *
backtrace(tm_thread *t, int skip)
{
@@ -1027,386 +1028,13 @@ static PLHashTable *new_allocations(void)
#define get_allocations() (allocations ? allocations : new_allocations())
#if defined(XP_UNIX) && !defined(XP_MACOSX)
NS_EXTERNAL_VIS_(__ptr_t)
malloc(size_t size)
{
PRUint32 start, end;
__ptr_t ptr;
callsite *site;
PLHashEntry *he;
allocation *alloc;
tm_thread *t;
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
return __libc_malloc(size);
}
start = PR_IntervalNow();
ptr = __libc_malloc(size);
end = PR_IntervalNow();
site = backtrace(t, 1);
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.malloc_calls++;
if (!ptr) {
tmstats.malloc_failures++;
} else {
if (site)
log_event5(logfp, TM_EVENT_MALLOC,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
return ptr;
}
NS_EXTERNAL_VIS_(__ptr_t)
calloc(size_t count, size_t size)
{
PRUint32 start, end;
__ptr_t ptr;
callsite *site;
PLHashEntry *he;
allocation *alloc;
tm_thread *t;
/**
* During the initialization of the glibc/libpthread, and
* before main() is running, ld-linux.so.2 tries to allocate memory
* using calloc (call from _dl_tls_setup).
*
* Thus, our calloc replacement is invoked too early, tries to
* initialize NSPR, which calls dlopen, which calls into the dl
* -> crash.
*
* Delaying NSPR calls until NSPR is initialized helps.
*/
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
return __libc_calloc(count, size);
}
start = PR_IntervalNow();
ptr = __libc_calloc(count, size);
end = PR_IntervalNow();
site = backtrace(t, 1);
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.calloc_calls++;
if (!ptr) {
tmstats.calloc_failures++;
} else {
size *= count;
if (site) {
log_event5(logfp, TM_EVENT_CALLOC,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
}
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
return ptr;
}
NS_EXTERNAL_VIS_(__ptr_t)
realloc(__ptr_t ptr, size_t size)
{
PRUint32 start, end;
__ptr_t oldptr;
callsite *oldsite, *site;
size_t oldsize;
PLHashNumber hash;
PLHashEntry **hep, *he;
allocation *alloc;
FILE *trackfp = NULL;
tm_thread *t;
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
return __libc_realloc(ptr, size);
}
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.realloc_calls++;
if (PR_TRUE) {
oldptr = ptr;
oldsite = NULL;
oldsize = 0;
he = NULL;
if (oldptr && get_allocations()) {
hash = hash_pointer(oldptr);
hep = PL_HashTableRawLookup(allocations, hash, oldptr);
he = *hep;
if (he) {
oldsite = (callsite*) he->value;
alloc = (allocation*) he;
oldsize = alloc->size;
trackfp = alloc->trackfp;
if (trackfp) {
fprintf(alloc->trackfp,
"\nrealloc(%p, %lu), oldsize %lu, alloc site %p\n",
(void*) ptr, (unsigned long) size,
(unsigned long) oldsize, (void*) oldsite);
NS_TraceStack(1, trackfp);
}
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
start = PR_IntervalNow();
ptr = __libc_realloc(ptr, size);
end = PR_IntervalNow();
site = backtrace(t, 1);
t->suppress_tracing++;
TM_ENTER_LOCK();
if (!ptr && size) {
/*
* When realloc() fails, the original block is not freed or moved, so
* we'll leave the allocation entry untouched.
*/
tmstats.realloc_failures++;
} else {
if (site) {
log_event8(logfp, TM_EVENT_REALLOC,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size,
oldsite ? oldsite->serial : 0,
(uint32)NS_PTR_TO_INT32(oldptr), oldsize);
}
if (ptr && allocations) {
if (ptr != oldptr) {
/*
* If we're reallocating (not merely allocating new space by
* passing null to realloc) and realloc has moved the block,
* free oldptr.
*/
if (he)
PL_HashTableRemove(allocations, oldptr);
/* Record the new allocation now, setting he. */
he = PL_HashTableAdd(allocations, ptr, site);
} else {
/*
* If we haven't yet recorded an allocation (possibly due to
* a temporary memory shortage), do it now.
*/
if (!he)
he = PL_HashTableAdd(allocations, ptr, site);
}
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = trackfp;
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
return ptr;
}
NS_EXTERNAL_VIS_(void*)
valloc(size_t size)
{
PRUint32 start, end;
__ptr_t ptr;
callsite *site;
PLHashEntry *he;
allocation *alloc;
tm_thread *t;
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
return __libc_valloc(size);
}
start = PR_IntervalNow();
ptr = __libc_valloc(size);
end = PR_IntervalNow();
site = backtrace(t, 1);
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.malloc_calls++; /* XXX valloc_calls ? */
if (!ptr) {
tmstats.malloc_failures++; /* XXX valloc_failures ? */
} else {
if (site)
log_event5(logfp, TM_EVENT_MALLOC, /* XXX TM_EVENT_VALLOC? */
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
return ptr;
}
NS_EXTERNAL_VIS_(void*)
memalign(size_t boundary, size_t size)
{
PRUint32 start, end;
__ptr_t ptr;
callsite *site;
PLHashEntry *he;
allocation *alloc;
tm_thread *t;
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
return __libc_memalign(boundary, size);
}
start = PR_IntervalNow();
ptr = __libc_memalign(boundary, size);
end = PR_IntervalNow();
site = backtrace(t, 1);
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.malloc_calls++; /* XXX memalign_calls ? */
if (!ptr) {
tmstats.malloc_failures++; /* XXX memalign_failures ? */
} else {
if (site) {
log_event5(logfp, TM_EVENT_MALLOC, /* XXX TM_EVENT_MEMALIGN? */
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
}
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
return ptr;
}
NS_EXTERNAL_VIS_(int)
posix_memalign(void **memptr, size_t alignment, size_t size)
{
__ptr_t ptr = memalign(alignment, size);
if (!ptr)
return ENOMEM;
*memptr = ptr;
return 0;
}
NS_EXTERNAL_VIS_(void)
free(__ptr_t ptr)
{
PLHashEntry **hep, *he;
callsite *site;
allocation *alloc;
uint32 serial = 0, size = 0;
PRUint32 start, end;
tm_thread *t;
if (!tracing_enabled || !PR_Initialized() ||
(t = tm_get_thread())->suppress_tracing != 0) {
__libc_free(ptr);
return;
}
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.free_calls++;
if (!ptr) {
tmstats.null_free_calls++;
} else {
if (get_allocations()) {
hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr);
he = *hep;
if (he) {
site = (callsite*) he->value;
if (site) {
alloc = (allocation*) he;
serial = site->serial;
size = alloc->size;
if (alloc->trackfp) {
fprintf(alloc->trackfp, "\nfree(%p), alloc site %p\n",
(void*) ptr, (void*) site);
NS_TraceStack(1, alloc->trackfp);
}
}
PL_HashTableRawRemove(allocations, hep, he);
}
}
}
TM_EXIT_LOCK();
t->suppress_tracing--;
start = PR_IntervalNow();
__libc_free(ptr);
end = PR_IntervalNow();
if (size != 0) {
t->suppress_tracing++;
TM_ENTER_LOCK();
log_event5(logfp, TM_EVENT_FREE,
serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
TM_EXIT_LOCK();
t->suppress_tracing--;
}
}
NS_EXTERNAL_VIS_(void)
cfree(void *ptr)
{
free(ptr);
}
#endif /* XP_UNIX */
#ifdef XP_MACOSX
#if defined(XP_MACOSX)
/* from malloc.c in Libc */
typedef void (malloc_logger_t)(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3, unsigned result, unsigned num_hot_frames_to_skip);
typedef void
malloc_logger_t(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3,
unsigned result, unsigned num_hot_frames_to_skip);
extern malloc_logger_t *malloc_logger;
#define MALLOC_LOG_TYPE_ALLOCATE 2
@@ -1438,6 +1066,128 @@ my_malloc_logger(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3,
}
}
static void
StartupHooker(void)
{
PR_ASSERT(!malloc_logger);
malloc_logger = my_malloc_logger;
}
static void
ShutdownHooker(void)
{
PR_ASSERT(malloc_logger == my_malloc_logger);
malloc_logger = NULL;
}
#elif defined(XP_UNIX)
static __ptr_t (*old_malloc_hook)(size_t size, __const __malloc_ptr_t caller);
static __ptr_t (*old_realloc_hook)(__ptr_t ptr, size_t size, __const __malloc_ptr_t caller);
static __ptr_t (*old_memalign_hook)(size_t boundary, size_t size, __const __malloc_ptr_t caller);
static void (*old_free_hook)(__ptr_t ptr, __const __malloc_ptr_t caller);
static __ptr_t
my_malloc_hook(size_t size, __const __malloc_ptr_t caller)
{
tm_thread *t;
PRUint32 start, end;
__ptr_t ptr;
PR_ASSERT(tracing_enabled);
t = tm_get_thread();
__malloc_hook = old_malloc_hook;
start = PR_IntervalNow();
ptr = __libc_malloc(size);
end = PR_IntervalNow();
__malloc_hook = my_malloc_hook;
MallocCallback(ptr, size, start, end, t);
return ptr;
}
static __ptr_t
my_realloc_hook(__ptr_t oldptr, size_t size, __const __malloc_ptr_t caller)
{
tm_thread *t;
PRUint32 start, end;
__ptr_t ptr;
PR_ASSERT(tracing_enabled);
t = tm_get_thread();
__realloc_hook = old_realloc_hook;
start = PR_IntervalNow();
ptr = __libc_realloc(oldptr, size);
end = PR_IntervalNow();
__realloc_hook = my_realloc_hook;
ReallocCallback(oldptr, ptr, size, start, end, t);
return ptr;
}
static __ptr_t
my_memalign_hook(size_t boundary, size_t size, __const __malloc_ptr_t caller)
{
tm_thread *t;
PRUint32 start, end;
__ptr_t ptr;
PR_ASSERT(tracing_enabled);
t = tm_get_thread();
__memalign_hook = old_memalign_hook;
start = PR_IntervalNow();
ptr = __libc_memalign(boundary, size);
end = PR_IntervalNow();
__memalign_hook = my_memalign_hook;
MallocCallback(ptr, size, start, end, t);
return ptr;
}
static void
my_free_hook(__ptr_t ptr, __const __malloc_ptr_t caller)
{
tm_thread *t;
PRUint32 start, end;
PR_ASSERT(tracing_enabled);
t = tm_get_thread();
__free_hook = old_free_hook;
start = PR_IntervalNow();
__libc_free(ptr);
end = PR_IntervalNow();
__free_hook = my_free_hook;
FreeCallback(ptr, start, end, t);
}
static void
StartupHooker(void)
{
PR_ASSERT(__malloc_hook != my_malloc_hook);
old_malloc_hook = __malloc_hook;
old_realloc_hook = __realloc_hook;
old_memalign_hook = __memalign_hook;
old_free_hook = __free_hook;
__malloc_hook = my_malloc_hook;
__realloc_hook = my_realloc_hook;
__memalign_hook = my_memalign_hook;
__free_hook = my_free_hook;
}
static void
ShutdownHooker(void)
{
PR_ASSERT(__malloc_hook == my_malloc_hook);
__malloc_hook = old_malloc_hook;
__realloc_hook = old_realloc_hook;
__memalign_hook = old_memalign_hook;
__free_hook = old_free_hook;
}
#elif defined(XP_WIN32)
/* See nsWinTraceMalloc.cpp. */
#endif
static const char magic[] = NS_TRACE_MALLOC_MAGIC;
@@ -1450,7 +1200,8 @@ log_header(int logfd)
(void) write(logfd, &ticksPerSec, sizeof ticksPerSec);
}
PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
PR_IMPLEMENT(void)
NS_TraceMallocStartup(int logfd)
{
/* We must be running on the primordial thread. */
PR_ASSERT(tracing_enabled == 1);
@@ -1482,18 +1233,10 @@ PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
tmlock = PR_NewLock();
main_thread.suppress_tracing--;
#ifdef XP_WIN32
/* Register listeners for win32. */
if (tracing_enabled) {
if (tracing_enabled)
StartupHooker();
}
#endif
#ifdef XP_MACOSX
malloc_logger = my_malloc_logger;
#endif
}
/*
* Options for log files, with the log file name either as the next option
* or separated by '=' (e.g. "./mozilla --trace-malloc * malloc.log" or
@@ -1517,7 +1260,8 @@ static const char SDLOG_OPTION[] = "--shutdown-leaks";
} \
PR_END_MACRO
PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
PR_IMPLEMENT(int)
NS_TraceMallocStartupArgs(int argc, char **argv)
{
int i, logfd = -1, consumed, logflags;
char *tmlogname = NULL; /* note global |sdlogname| */
@@ -1636,7 +1380,8 @@ PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
return argc;
}
PR_IMPLEMENT(void) NS_TraceMallocShutdown(void)
PR_IMPLEMENT(void)
NS_TraceMallocShutdown(void)
{
logfile *fp;
@@ -1669,39 +1414,52 @@ PR_IMPLEMENT(void) NS_TraceMallocShutdown(void)
tmlock = NULL;
PR_DestroyLock(lock);
}
#ifdef XP_WIN32
if (tracing_enabled) {
tracing_enabled = 0;
ShutdownHooker();
}
#endif
}
PR_IMPLEMENT(void) NS_TraceMallocDisable(void)
PR_IMPLEMENT(void)
NS_TraceMallocDisable(void)
{
logfile *fp;
tm_thread *t = tm_get_thread();
logfile *fp;
uint32 sample;
/* Robustify in case of duplicate call. */
PR_ASSERT(tracing_enabled);
if (tracing_enabled == 0)
return;
t->suppress_tracing++;
TM_ENTER_LOCK();
for (fp = logfile_list; fp; fp = fp->next)
flush_logfile(fp);
tracing_enabled = 0;
sample = --tracing_enabled;
TM_EXIT_LOCK();
t->suppress_tracing--;
if (sample == 0)
ShutdownHooker();
}
PR_IMPLEMENT(void) NS_TraceMallocEnable(void)
PR_IMPLEMENT(void)
NS_TraceMallocEnable(void)
{
tm_thread *t = tm_get_thread();
uint32 sample;
t->suppress_tracing++;
TM_ENTER_LOCK();
tracing_enabled = 1;
sample = ++tracing_enabled;
TM_EXIT_LOCK();
t->suppress_tracing--;
if (sample == 1)
StartupHooker();
}
PR_IMPLEMENT(int) NS_TraceMallocChangeLogFD(int fd)
PR_IMPLEMENT(int)
NS_TraceMallocChangeLogFD(int fd)
{
logfile *oldfp, *fp;
struct stat sb;
@@ -1841,8 +1599,9 @@ allocation_enumerator(PLHashEntry *he, PRIntn i, void *arg)
for (p = (unsigned long*) he->key,
end = (unsigned long*) ((char*)he->key + alloc->size);
p < end; ++p)
p < end; ++p) {
fprintf(ofp, "\t0x%08lX\n", *p);
}
while (site) {
if (site->name || site->parent) {
@@ -1884,9 +1643,10 @@ NS_TraceMallocDumpAllocations(const char *pathname)
ofp = fopen(pathname, WRITE_FLAGS);
if (ofp) {
if (allocations)
if (allocations) {
PL_HashTableEnumerateEntries(allocations, allocation_enumerator,
ofp);
}
rv = ferror(ofp) ? -1 : 0;
fclose(ofp);
} else {
@@ -1918,7 +1678,6 @@ NS_TraceMallocFlushLogfiles(void)
PR_IMPLEMENT(void)
NS_TrackAllocation(void* ptr, FILE *ofp)
{
PLHashEntry **hep;
allocation *alloc;
tm_thread *t = tm_get_thread();
@@ -1928,8 +1687,8 @@ NS_TrackAllocation(void* ptr, FILE *ofp)
t->suppress_tracing++;
TM_ENTER_LOCK();
if (get_allocations()) {
hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr);
alloc = (allocation*) *hep;
alloc = (allocation*)
*PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr);
if (alloc) {
fprintf(ofp, "Tracking %p\n", (void*) ptr);
alloc->trackfp = ofp;
@@ -1941,8 +1700,6 @@ NS_TrackAllocation(void* ptr, FILE *ofp)
t->suppress_tracing--;
}
#if defined(XP_WIN32) || defined(XP_MACOSX)
PR_IMPLEMENT(void)
MallocCallback(void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread *t)
{
@@ -1961,15 +1718,17 @@ MallocCallback(void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread *
if (!ptr) {
tmstats.malloc_failures++;
} else {
if (site)
if (site) {
log_event5(logfp, TM_EVENT_MALLOC,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
}
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
@@ -1996,15 +1755,17 @@ CallocCallback(void *ptr, size_t count, size_t size, PRUint32 start, PRUint32 en
tmstats.calloc_failures++;
} else {
size *= count;
if (site)
if (site) {
log_event5(logfp, TM_EVENT_CALLOC,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), size);
}
if (get_allocations()) {
he = PL_HashTableAdd(allocations, ptr, site);
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = NULL;
}
}
}
@@ -2013,13 +1774,15 @@ CallocCallback(void *ptr, size_t count, size_t size, PRUint32 start, PRUint32 en
}
PR_IMPLEMENT(void)
ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread *t)
ReallocCallback(void * oldptr, void *ptr, size_t size,
PRUint32 start, PRUint32 end, tm_thread *t)
{
callsite *oldsite, *site;
size_t oldsize;
PLHashNumber hash;
PLHashEntry **hep, *he;
allocation *alloc;
FILE *trackfp = NULL;
if (!tracing_enabled || t->suppress_tracing != 0)
return;
@@ -2029,28 +1792,34 @@ ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32
t->suppress_tracing++;
TM_ENTER_LOCK();
tmstats.realloc_calls++;
if (PR_TRUE) {
oldsite = NULL;
oldsize = 0;
he = NULL;
if (oldptr && get_allocations()) {
hash = hash_pointer(oldptr);
hep = PL_HashTableRawLookup(allocations, hash, oldptr);
he = *hep;
if (he) {
oldsite = (callsite*) he->value;
alloc = (allocation*) he;
oldsize = alloc->size;
oldsite = NULL;
oldsize = 0;
hep = NULL;
he = NULL;
if (oldptr && get_allocations()) {
hash = hash_pointer(oldptr);
hep = PL_HashTableRawLookup(allocations, hash, oldptr);
he = *hep;
if (he) {
oldsite = (callsite*) he->value;
alloc = (allocation*) he;
oldsize = alloc->size;
trackfp = alloc->trackfp;
if (trackfp) {
fprintf(alloc->trackfp,
"\nrealloc(%p, %lu), oldsize %lu, alloc site %p\n",
(void*) ptr, (unsigned long) size,
(unsigned long) oldsize, (void*) oldsite);
NS_TraceStack(1, trackfp);
}
}
}
if (!ptr && size) {
tmstats.realloc_failures++;
/*
* When realloc() fails, the original block is not freed or moved, so
* we'll leave the allocation entry untouched.
*/
tmstats.realloc_failures++;
} else {
if (site) {
log_event8(logfp, TM_EVENT_REALLOC,
@@ -2081,6 +1850,7 @@ ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32
if (he) {
alloc = (allocation*) he;
alloc->size = size;
alloc->trackfp = trackfp;
}
}
}
@@ -2111,6 +1881,11 @@ FreeCallback(void * ptr, PRUint32 start, PRUint32 end, tm_thread *t)
site = (callsite*) he->value;
if (site) {
alloc = (allocation*) he;
if (alloc->trackfp) {
fprintf(alloc->trackfp, "\nfree(%p), alloc site %p\n",
(void*) ptr, (void*) site);
NS_TraceStack(1, alloc->trackfp);
}
log_event5(logfp, TM_EVENT_FREE,
site->serial, start, end - start,
(uint32)NS_PTR_TO_INT32(ptr), alloc->size);
@@ -2123,6 +1898,4 @@ FreeCallback(void * ptr, PRUint32 start, PRUint32 end, tm_thread *t)
t->suppress_tracing--;
}
#endif /* defined(XP_WIN32) || defined(XP_MACOSX) */
#endif /* NS_TRACE_MALLOC */

View File

@@ -69,13 +69,11 @@ struct tm_thread {
/* implemented in nsTraceMalloc.c */
tm_thread * tm_get_thread(void);
#if defined(XP_WIN32) || defined(XP_MACOSX)
/* implemented in nsTraceMalloc.c */
PR_EXTERN(void) MallocCallback(void *aPtr, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t);
PR_EXTERN(void) CallocCallback(void *aPtr, size_t aCount, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t);
PR_EXTERN(void) ReallocCallback(void *aPin, void* aPout, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t);
PR_EXTERN(void) FreeCallback(void *aPtr, PRUint32 start, PRUint32 end, tm_thread *t);
#endif
#ifdef XP_WIN32
/* implemented in nsTraceMalloc.c */