diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | malloc/memusage.c | 139 | ||||
-rw-r--r-- | sysdeps/ia64/hp-timing.h | 6 | ||||
-rw-r--r-- | sysdeps/ia64/memusage.h | 10 |
4 files changed, 103 insertions, 68 deletions
@@ -1,3 +1,19 @@ +2001-08-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/ia64/memusage.h (GETTIME): Define using hp-timing.h + funcationality. + + * sysdeps/ia64/hp-timing.h (HP_TIMING_NOW): Fix comment. + +2001-08-07 Jakub Jelinek <jakub@redhat.com> + + * malloc/memusage.c (initialized): New variable. + (init): If not yet initialized, call me(). + (me): Do all dlsym calls here. + (malloc, realloc, calloc, free): If not yet initialized, + call me(). If in the middle of initializing, return NULL or + do nothing. + 2001-08-07 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/seekdir.c (seekdir): Set dirp->filepos. diff --git a/malloc/memusage.c b/malloc/memusage.c index 6ae5479b79..b65440f807 100644 --- a/malloc/memusage.c +++ b/malloc/memusage.c @@ -82,6 +82,7 @@ static size_t buffer_size; static int fd = -1; static int not_me; +static int initialized; extern const char *__progname; struct entry @@ -157,15 +158,6 @@ int_handler (int signo) } -/* Record the initial stack position. */ -static void -__attribute__ ((constructor)) -init (void) -{ - start_sp = GETSP (); -} - - /* Find out whether this is the program we are supposed to profile. For this the name in the variable `__progname' must match the one given in the environment variable MEMUSAGE_PROG_NAME. If the variable @@ -187,6 +179,7 @@ me (void) { const char *env = getenv ("MEMUSAGE_PROG_NAME"); size_t prog_len = strlen (__progname); + if (env != NULL) { /* Check for program name. */ @@ -199,7 +192,19 @@ me (void) /* Only open the file if it's really us. */ if (!not_me && fd == -1) { - const char *outname = getenv ("MEMUSAGE_OUTPUT"); + const char *outname; + + if (!start_sp) + start_sp = GETSP (); + + initialized = -1; + mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc"); + reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc"); + callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc"); + freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free"); + initialized = 1; + + outname = getenv ("MEMUSAGE_OUTPUT"); if (outname != NULL && outname[0] != '\0' && access (outname, R_OK | W_OK) == 0) { @@ -253,6 +258,17 @@ me (void) } +/* Record the initial stack position. */ +static void +__attribute__ ((constructor)) +init (void) +{ + start_sp = GETSP (); + if (! initialized) + me (); +} + + /* `malloc' replacement. We keep track of the memory usage if this is the correct program. */ void * @@ -261,10 +277,11 @@ malloc (size_t len) struct header *result = NULL; /* Determine real implementation if not already happened. */ - if (mallocp == NULL) + if (__builtin_expect (initialized <= 0, 0)) { + if (initialized == -1) + return NULL; me (); - mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc"); } /* If this is not the correct program just use the normal function. */ @@ -287,15 +304,17 @@ malloc (size_t len) /* Do the real work. */ result = (struct header *) (*mallocp) (len + sizeof (struct header)); - if (result == NULL) - ++failed[idx_malloc]; - else - /* Update the allocation data and write out the records if necessary. */ - update_data (result, len, 0); + { + ++failed[idx_malloc]; + return NULL; + } + + /* Update the allocation data and write out the records if necessary. */ + update_data (result, len, 0); /* Return the pointer to the user buffer. */ - return result ? (void *) (result + 1) : NULL; + return (void *) (result + 1); } @@ -309,10 +328,11 @@ realloc (void *old, size_t len) size_t old_len; /* Determine real implementation if not already happened. */ - if (reallocp == NULL) + if (__builtin_expect (initialized <= 0, 0)) { + if (initialized == -1) + return NULL; me (); - reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc"); } /* If this is not the correct program just use the normal function. */ @@ -350,24 +370,24 @@ realloc (void *old, size_t len) /* Do the real work. */ result = (struct header *) (*reallocp) (real, len + sizeof (struct header)); - if (result == NULL) - ++failed[idx_realloc]; - else { - /* Record whether the reduction/increase happened in place. */ - if (real == result) - ++inplace; - /* Was the buffer increased? */ - if (old_len > len) - ++decreasing; - - /* Update the allocation data and write out the records if necessary. */ - update_data (result, len, old_len); + ++failed[idx_realloc]; + return NULL; } + /* Record whether the reduction/increase happened in place. */ + if (real == result) + ++inplace; + /* Was the buffer increased? */ + if (old_len > len) + ++decreasing; + + /* Update the allocation data and write out the records if necessary. */ + update_data (result, len, old_len); + /* Return the pointer to the user buffer. */ - return result ? (void *) (result + 1) : NULL; + return (void *) (result + 1); } @@ -379,23 +399,17 @@ calloc (size_t n, size_t len) struct header *result; size_t size = n * len; - /* Determine real implementation if not already happened. We are - searching for the `malloc' implementation since it is not always - efficiently possible to use `calloc' because we have to add a bit - room to the allocation to put the header in. */ - if (mallocp == NULL) + /* Determine real implementation if not already happened. */ + if (__builtin_expect (initialized <= 0, 0)) { + if (initialized == -1) + return NULL; me (); - mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc"); } /* If this is not the correct program just use the normal function. */ if (not_me) - { - callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc"); - - return (*callocp) (n, len); - } + return (*callocp) (n, len); /* Keep track of number of calls. */ ++calls[idx_calloc]; @@ -413,17 +427,17 @@ calloc (size_t n, size_t len) /* Do the real work. */ result = (struct header *) (*mallocp) (size + sizeof (struct header)); - if (result != NULL) - memset (result + 1, '\0', size); - if (result == NULL) - ++failed[idx_calloc]; - else - /* Update the allocation data and write out the records if necessary. */ - update_data (result, size, 0); + { + ++failed[idx_calloc]; + return NULL; + } - /* Return the pointer to the user buffer. */ - return result ? (void *) (result + 1) : NULL; + /* Update the allocation data and write out the records if necessary. */ + update_data (result, size, 0); + + /* Do what `calloc' would have done and return the buffer to the caller. */ + return memset (result + 1, '\0', size); } @@ -434,18 +448,12 @@ free (void *ptr) { struct header *real; - /* `free (NULL)' has no effect. */ - if (ptr == NULL) - { - ++calls[idx_free]; - return; - } - /* Determine real implementation if not already happened. */ - if (freep == NULL) + if (__builtin_expect (initialized <= 0, 0)) { + if (initialized == -1) + return; me (); - freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free"); } /* If this is not the correct program just use the normal function. */ @@ -455,6 +463,13 @@ free (void *ptr) return; } + /* `free (NULL)' has no effect. */ + if (ptr == NULL) + { + ++calls[idx_free]; + return; + } + /* Determine the pointer to the header. */ real = ((struct header *) ptr) - 1; if (real->magic != MAGIC) diff --git a/sysdeps/ia64/hp-timing.h b/sysdeps/ia64/hp-timing.h index ed1dc6067e..da2cd8e9c6 100644 --- a/sysdeps/ia64/hp-timing.h +++ b/sysdeps/ia64/hp-timing.h @@ -92,11 +92,7 @@ extern hp_timing_t __libc_hp_timing_overhead; processor implementation. */ #define REPEAT_READ(val) __builtin_expect ((int) val == -1, 0) -/* That's quite simple. Use the `rdtsc' instruction. Note that the value - might not be 100% accurate since there might be some more instructions - running in this moment. This could be changed by using a barrier like - 'cpuid' right before the `rdtsc' instruciton. But we are not interested - in accurate clock cycles here so we don't do this. */ +/* That's quite simple. Use the `ar.itc' instruction. */ #define HP_TIMING_NOW(Var) \ ({ unsigned long int __itc; \ do \ diff --git a/sysdeps/ia64/memusage.h b/sysdeps/ia64/memusage.h index 5ca0782e2c..5f395b88d6 100644 --- a/sysdeps/ia64/memusage.h +++ b/sysdeps/ia64/memusage.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,7 +16,15 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <hp-timing.h> #define GETSP() ({ register uintptr_t stack_ptr asm ("%r12"); stack_ptr; }) +#define GETTIME(low, high) \ + { \ + hp_timing_t __now; \ + HP_TIMING_NOW (__now); \ + low = __now & 0xffffffff; \ + high = __now >> 32; \ + } #include <sysdeps/generic/memusage.h> |