Blame malloc/memusage.c

Packit Service 82fcde
/* Profile heap and stack memory usage of running program.
Packit Service 82fcde
   Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <atomic.h>
Packit Service 82fcde
#include <dlfcn.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <inttypes.h>
Packit Service 82fcde
#include <signal.h>
Packit Service 82fcde
#include <stdarg.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <sys/mman.h>
Packit Service 82fcde
#include <sys/time.h>
Packit Service 82fcde
Packit Service 82fcde
#include <memusage.h>
Packit Service 82fcde
Packit Service 82fcde
/* Pointer to the real functions.  These are determined used `dlsym'
Packit Service 82fcde
   when really needed.  */
Packit Service 82fcde
static void *(*mallocp)(size_t);
Packit Service 82fcde
static void *(*reallocp) (void *, size_t);
Packit Service 82fcde
static void *(*callocp) (size_t, size_t);
Packit Service 82fcde
static void (*freep) (void *);
Packit Service 82fcde
Packit Service 82fcde
static void *(*mmapp) (void *, size_t, int, int, int, off_t);
Packit Service 82fcde
static void *(*mmap64p) (void *, size_t, int, int, int, off64_t);
Packit Service 82fcde
static int (*munmapp) (void *, size_t);
Packit Service 82fcde
static void *(*mremapp) (void *, size_t, size_t, int, void *);
Packit Service 82fcde
Packit Service 82fcde
enum
Packit Service 82fcde
{
Packit Service 82fcde
  idx_malloc = 0,
Packit Service 82fcde
  idx_realloc,
Packit Service 82fcde
  idx_calloc,
Packit Service 82fcde
  idx_free,
Packit Service 82fcde
  idx_mmap_r,
Packit Service 82fcde
  idx_mmap_w,
Packit Service 82fcde
  idx_mmap_a,
Packit Service 82fcde
  idx_mremap,
Packit Service 82fcde
  idx_munmap,
Packit Service 82fcde
  idx_last
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct header
Packit Service 82fcde
{
Packit Service 82fcde
  size_t length;
Packit Service 82fcde
  size_t magic;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
#define MAGIC 0xfeedbeaf
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static memusage_cntr_t calls[idx_last];
Packit Service 82fcde
static memusage_cntr_t failed[idx_last];
Packit Service 82fcde
static memusage_size_t total[idx_last];
Packit Service 82fcde
static memusage_size_t grand_total;
Packit Service 82fcde
static memusage_cntr_t histogram[65536 / 16];
Packit Service 82fcde
static memusage_cntr_t large;
Packit Service 82fcde
static memusage_cntr_t calls_total;
Packit Service 82fcde
static memusage_cntr_t inplace;
Packit Service 82fcde
static memusage_cntr_t decreasing;
Packit Service 82fcde
static memusage_cntr_t realloc_free;
Packit Service 82fcde
static memusage_cntr_t inplace_mremap;
Packit Service 82fcde
static memusage_cntr_t decreasing_mremap;
Packit Service 82fcde
static memusage_size_t current_heap;
Packit Service 82fcde
static memusage_size_t peak_use[3];
Packit Service 82fcde
static __thread uintptr_t start_sp;
Packit Service 82fcde
Packit Service 82fcde
/* A few macros to make the source more readable.  */
Packit Service 82fcde
#define peak_heap       peak_use[0]
Packit Service 82fcde
#define peak_stack      peak_use[1]
Packit Service 82fcde
#define peak_total      peak_use[2]
Packit Service 82fcde
Packit Service 82fcde
#define DEFAULT_BUFFER_SIZE     32768
Packit Service 82fcde
static size_t buffer_size;
Packit Service 82fcde
Packit Service 82fcde
static int fd = -1;
Packit Service 82fcde
Packit Service 82fcde
static bool not_me;
Packit Service 82fcde
static int initialized;
Packit Service 82fcde
static bool trace_mmap;
Packit Service 82fcde
extern const char *__progname;
Packit Service 82fcde
Packit Service 82fcde
struct entry
Packit Service 82fcde
{
Packit Service 82fcde
  uint64_t heap;
Packit Service 82fcde
  uint64_t stack;
Packit Service 82fcde
  uint32_t time_low;
Packit Service 82fcde
  uint32_t time_high;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static struct entry buffer[2 * DEFAULT_BUFFER_SIZE];
Packit Service 82fcde
static uatomic32_t buffer_cnt;
Packit Service 82fcde
static struct entry first;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Update the global data after a successful function call.  */
Packit Service 82fcde
static void
Packit Service 82fcde
update_data (struct header *result, size_t len, size_t old_len)
Packit Service 82fcde
{
Packit Service 82fcde
  if (result != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Record the information we need and mark the block using a
Packit Service 82fcde
         magic number.  */
Packit Service 82fcde
      result->length = len;
Packit Service 82fcde
      result->magic = MAGIC;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Compute current heap usage and compare it with the maximum value.  */
Packit Service 82fcde
  memusage_size_t heap
Packit Service 82fcde
    = catomic_exchange_and_add (&current_heap, len - old_len) + len - old_len;
Packit Service 82fcde
  catomic_max (&peak_heap, heap);
Packit Service 82fcde
Packit Service 82fcde
  /* Compute current stack usage and compare it with the maximum
Packit Service 82fcde
     value.  The base stack pointer might not be set if this is not
Packit Service 82fcde
     the main thread and it is the first call to any of these
Packit Service 82fcde
     functions.  */
Packit Service 82fcde
  if (__glibc_unlikely (!start_sp))
Packit Service 82fcde
    start_sp = GETSP ();
Packit Service 82fcde
Packit Service 82fcde
  uintptr_t sp = GETSP ();
Packit Service 82fcde
#ifdef STACK_GROWS_UPWARD
Packit Service 82fcde
  /* This can happen in threads where we didn't catch the thread's
Packit Service 82fcde
     stack early enough.  */
Packit Service 82fcde
  if (__glibc_unlikely (sp < start_sp))
Packit Service 82fcde
    start_sp = sp;
Packit Service 82fcde
  size_t current_stack = sp - start_sp;
Packit Service 82fcde
#else
Packit Service 82fcde
  /* This can happen in threads where we didn't catch the thread's
Packit Service 82fcde
     stack early enough.  */
Packit Service 82fcde
  if (__glibc_unlikely (sp > start_sp))
Packit Service 82fcde
    start_sp = sp;
Packit Service 82fcde
  size_t current_stack = start_sp - sp;
Packit Service 82fcde
#endif
Packit Service 82fcde
  catomic_max (&peak_stack, current_stack);
Packit Service 82fcde
Packit Service 82fcde
  /* Add up heap and stack usage and compare it with the maximum value.  */
Packit Service 82fcde
  catomic_max (&peak_total, heap + current_stack);
Packit Service 82fcde
Packit Service 82fcde
  /* Store the value only if we are writing to a file.  */
Packit Service 82fcde
  if (fd != -1)
Packit Service 82fcde
    {
Packit Service 82fcde
      uatomic32_t idx = catomic_exchange_and_add (&buffer_cnt, 1);
Packit Service 82fcde
      if (idx + 1 >= 2 * buffer_size)
Packit Service 82fcde
        {
Packit Service 82fcde
          /* We try to reset the counter to the correct range.  If
Packit Service 82fcde
             this fails because of another thread increasing the
Packit Service 82fcde
             counter it does not matter since that thread will take
Packit Service 82fcde
             care of the correction.  */
Packit Service 82fcde
          uatomic32_t reset = (idx + 1) % (2 * buffer_size);
Packit Service 82fcde
          catomic_compare_and_exchange_val_acq (&buffer_cnt, reset, idx + 1);
Packit Service 82fcde
          if (idx >= 2 * buffer_size)
Packit Service 82fcde
            idx = reset - 1;
Packit Service 82fcde
        }
Packit Service 82fcde
      assert (idx < 2 * DEFAULT_BUFFER_SIZE);
Packit Service 82fcde
Packit Service 82fcde
      buffer[idx].heap = current_heap;
Packit Service 82fcde
      buffer[idx].stack = current_stack;
Packit Service 82fcde
      GETTIME (buffer[idx].time_low, buffer[idx].time_high);
Packit Service 82fcde
Packit Service 82fcde
      /* Write out buffer if it is full.  */
Packit Service 82fcde
      if (idx + 1 == buffer_size)
Packit Service 82fcde
        write (fd, buffer, buffer_size * sizeof (struct entry));
Packit Service 82fcde
      else if (idx + 1 == 2 * buffer_size)
Packit Service 82fcde
        write (fd, &buffer[buffer_size], buffer_size * sizeof (struct entry));
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Interrupt handler.  */
Packit Service 82fcde
static void
Packit Service 82fcde
int_handler (int signo)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Nothing gets allocated.  Just record the stack pointer position.  */
Packit Service 82fcde
  update_data (NULL, 0, 0);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Find out whether this is the program we are supposed to profile.
Packit Service 82fcde
   For this the name in the variable `__progname' must match the one
Packit Service 82fcde
   given in the environment variable MEMUSAGE_PROG_NAME.  If the variable
Packit Service 82fcde
   is not present every program assumes it should be profiling.
Packit Service 82fcde
Packit Service 82fcde
   If this is the program open a file descriptor to the output file.
Packit Service 82fcde
   We will write to it whenever the buffer overflows.  The name of the
Packit Service 82fcde
   output file is determined by the environment variable MEMUSAGE_OUTPUT.
Packit Service 82fcde
Packit Service 82fcde
   If the environment variable MEMUSAGE_BUFFER_SIZE is set its numerical
Packit Service 82fcde
   value determines the size of the internal buffer.  The number gives
Packit Service 82fcde
   the number of elements in the buffer.  By setting the number to one
Packit Service 82fcde
   one effectively selects unbuffered operation.
Packit Service 82fcde
Packit Service 82fcde
   If MEMUSAGE_NO_TIMER is not present an alarm handler is installed
Packit Service 82fcde
   which at the highest possible frequency records the stack pointer.  */
Packit Service 82fcde
static void
Packit Service 82fcde
me (void)
Packit Service 82fcde
{
Packit Service 82fcde
  const char *env = getenv ("MEMUSAGE_PROG_NAME");
Packit Service 82fcde
  size_t prog_len = strlen (__progname);
Packit Service 82fcde
Packit Service 82fcde
  initialized = -1;
Packit Service 82fcde
  mallocp = (void *(*)(size_t))dlsym (RTLD_NEXT, "malloc");
Packit Service 82fcde
  reallocp = (void *(*)(void *, size_t))dlsym (RTLD_NEXT, "realloc");
Packit Service 82fcde
  callocp = (void *(*)(size_t, size_t))dlsym (RTLD_NEXT, "calloc");
Packit Service 82fcde
  freep = (void (*)(void *))dlsym (RTLD_NEXT, "free");
Packit Service 82fcde
Packit Service 82fcde
  mmapp = (void *(*)(void *, size_t, int, int, int, off_t))dlsym (RTLD_NEXT,
Packit Service 82fcde
                                                                  "mmap");
Packit Service 82fcde
  mmap64p =
Packit Service 82fcde
    (void *(*)(void *, size_t, int, int, int, off64_t))dlsym (RTLD_NEXT,
Packit Service 82fcde
                                                              "mmap64");
Packit Service 82fcde
  mremapp = (void *(*)(void *, size_t, size_t, int, void *))dlsym (RTLD_NEXT,
Packit Service 82fcde
                                                                   "mremap");
Packit Service 82fcde
  munmapp = (int (*)(void *, size_t))dlsym (RTLD_NEXT, "munmap");
Packit Service 82fcde
  initialized = 1;
Packit Service 82fcde
Packit Service 82fcde
  if (env != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Check for program name.  */
Packit Service 82fcde
      size_t len = strlen (env);
Packit Service 82fcde
      if (len > prog_len || strcmp (env, &__progname[prog_len - len]) != 0
Packit Service 82fcde
          || (prog_len != len && __progname[prog_len - len - 1] != '/'))
Packit Service 82fcde
        not_me = true;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Only open the file if it's really us.  */
Packit Service 82fcde
  if (!not_me && fd == -1)
Packit Service 82fcde
    {
Packit Service 82fcde
      const char *outname;
Packit Service 82fcde
Packit Service 82fcde
      if (!start_sp)
Packit Service 82fcde
        start_sp = GETSP ();
Packit Service 82fcde
Packit Service 82fcde
      outname = getenv ("MEMUSAGE_OUTPUT");
Packit Service 82fcde
      if (outname != NULL && outname[0] != '\0'
Packit Service 82fcde
          && (access (outname, R_OK | W_OK) == 0 || errno == ENOENT))
Packit Service 82fcde
        {
Packit Service 82fcde
          fd = creat64 (outname, 0666);
Packit Service 82fcde
Packit Service 82fcde
          if (fd == -1)
Packit Service 82fcde
            /* Don't do anything in future calls if we cannot write to
Packit Service 82fcde
               the output file.  */
Packit Service 82fcde
            not_me = true;
Packit Service 82fcde
          else
Packit Service 82fcde
            {
Packit Service 82fcde
              /* Write the first entry.  */
Packit Service 82fcde
              first.heap = 0;
Packit Service 82fcde
              first.stack = 0;
Packit Service 82fcde
              GETTIME (first.time_low, first.time_high);
Packit Service 82fcde
              /* Write it two times since we need the starting and end time. */
Packit Service 82fcde
              write (fd, &first, sizeof (first));
Packit Service 82fcde
              write (fd, &first, sizeof (first));
Packit Service 82fcde
Packit Service 82fcde
              /* Determine the buffer size.  We use the default if the
Packit Service 82fcde
                 environment variable is not present.  */
Packit Service 82fcde
              buffer_size = DEFAULT_BUFFER_SIZE;
Packit Service 82fcde
              const char *str_buffer_size = getenv ("MEMUSAGE_BUFFER_SIZE");
Packit Service 82fcde
              if (str_buffer_size != NULL)
Packit Service 82fcde
                {
Packit Service 82fcde
                  buffer_size = atoi (str_buffer_size);
Packit Service 82fcde
                  if (buffer_size == 0 || buffer_size > DEFAULT_BUFFER_SIZE)
Packit Service 82fcde
                    buffer_size = DEFAULT_BUFFER_SIZE;
Packit Service 82fcde
                }
Packit Service 82fcde
Packit Service 82fcde
              /* Possibly enable timer-based stack pointer retrieval.  */
Packit Service 82fcde
              if (getenv ("MEMUSAGE_NO_TIMER") == NULL)
Packit Service 82fcde
                {
Packit Service 82fcde
                  struct sigaction act;
Packit Service 82fcde
Packit Service 82fcde
                  act.sa_handler = (sighandler_t) &int_handler;
Packit Service 82fcde
                  act.sa_flags = SA_RESTART;
Packit Service 82fcde
                  sigfillset (&act.sa_mask);
Packit Service 82fcde
Packit Service 82fcde
                  if (sigaction (SIGPROF, &act, NULL) >= 0)
Packit Service 82fcde
                    {
Packit Service 82fcde
                      struct itimerval timer;
Packit Service 82fcde
Packit Service 82fcde
                      timer.it_value.tv_sec = 0;
Packit Service 82fcde
                      timer.it_value.tv_usec = 1;
Packit Service 82fcde
                      timer.it_interval = timer.it_value;
Packit Service 82fcde
                      setitimer (ITIMER_PROF, &timer, NULL);
Packit Service 82fcde
                    }
Packit Service 82fcde
                }
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 82fcde
Packit Service 82fcde
      if (!not_me && getenv ("MEMUSAGE_TRACE_MMAP") != NULL)
Packit Service 82fcde
        trace_mmap = true;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Record the initial stack position.  */
Packit Service 82fcde
static void
Packit Service 82fcde
__attribute__ ((constructor))
Packit Service 82fcde
init (void)
Packit Service 82fcde
{
Packit Service 82fcde
  start_sp = GETSP ();
Packit Service 82fcde
  if (!initialized)
Packit Service 82fcde
    me ();
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `malloc' replacement.  We keep track of the memory usage if this is the
Packit Service 82fcde
   correct program.  */
Packit Service 82fcde
void *
Packit Service 82fcde
malloc (size_t len)
Packit Service 82fcde
{
Packit Service 82fcde
  struct header *result = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If this is not the correct program just use the normal function.  */
Packit Service 82fcde
  if (not_me)
Packit Service 82fcde
    return (*mallocp)(len);
Packit Service 82fcde
Packit Service 82fcde
  /* Keep track of number of calls.  */
Packit Service 82fcde
  catomic_increment (&calls[idx_malloc]);
Packit Service 82fcde
  /* Keep track of total memory consumption for `malloc'.  */
Packit Service 82fcde
  catomic_add (&total[idx_malloc], len);
Packit Service 82fcde
  /* Keep track of total memory requirement.  */
Packit Service 82fcde
  catomic_add (&grand_total, len);
Packit Service 82fcde
  /* Remember the size of the request.  */
Packit Service 82fcde
  if (len < 65536)
Packit Service 82fcde
    catomic_increment (&histogram[len / 16]);
Packit Service 82fcde
  else
Packit Service 82fcde
    catomic_increment (&large);
Packit Service 82fcde
  /* Total number of calls of any of the functions.  */
Packit Service 82fcde
  catomic_increment (&calls_total);
Packit Service 82fcde
Packit Service 82fcde
  /* Do the real work.  */
Packit Service 82fcde
  result = (struct header *) (*mallocp)(len + sizeof (struct header));
Packit Service 82fcde
  if (result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      catomic_increment (&failed[idx_malloc]);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Update the allocation data and write out the records if necessary.  */
Packit Service 82fcde
  update_data (result, len, 0);
Packit Service 82fcde
Packit Service 82fcde
  /* Return the pointer to the user buffer.  */
Packit Service 82fcde
  return (void *) (result + 1);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `realloc' replacement.  We keep track of the memory usage if this is the
Packit Service 82fcde
   correct program.  */
Packit Service 82fcde
void *
Packit Service 82fcde
realloc (void *old, size_t len)
Packit Service 82fcde
{
Packit Service 82fcde
  struct header *result = NULL;
Packit Service 82fcde
  struct header *real;
Packit Service 82fcde
  size_t old_len;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If this is not the correct program just use the normal function.  */
Packit Service 82fcde
  if (not_me)
Packit Service 82fcde
    return (*reallocp)(old, len);
Packit Service 82fcde
Packit Service 82fcde
  if (old == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This is really a `malloc' call.  */
Packit Service 82fcde
      real = NULL;
Packit Service 82fcde
      old_len = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      real = ((struct header *) old) - 1;
Packit Service 82fcde
      if (real->magic != MAGIC)
Packit Service 82fcde
        /* This is no memory allocated here.  */
Packit Service 82fcde
        return (*reallocp)(old, len);
Packit Service 82fcde
Packit Service 82fcde
      old_len = real->length;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Keep track of number of calls.  */
Packit Service 82fcde
  catomic_increment (&calls[idx_realloc]);
Packit Service 82fcde
  if (len > old_len)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Keep track of total memory consumption for `realloc'.  */
Packit Service 82fcde
      catomic_add (&total[idx_realloc], len - old_len);
Packit Service 82fcde
      /* Keep track of total memory requirement.  */
Packit Service 82fcde
      catomic_add (&grand_total, len - old_len);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (len == 0 && old != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Special case.  */
Packit Service 82fcde
      catomic_increment (&realloc_free);
Packit Service 82fcde
      /* Keep track of total memory freed using `free'.  */
Packit Service 82fcde
      catomic_add (&total[idx_free], real->length);
Packit Service 82fcde
Packit Service 82fcde
      /* Update the allocation data and write out the records if necessary.  */
Packit Service 82fcde
      update_data (NULL, 0, old_len);
Packit Service 82fcde
Packit Service 82fcde
      /* Do the real work.  */
Packit Service 82fcde
      (*freep) (real);
Packit Service 82fcde
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Remember the size of the request.  */
Packit Service 82fcde
  if (len < 65536)
Packit Service 82fcde
    catomic_increment (&histogram[len / 16]);
Packit Service 82fcde
  else
Packit Service 82fcde
    catomic_increment (&large);
Packit Service 82fcde
  /* Total number of calls of any of the functions.  */
Packit Service 82fcde
  catomic_increment (&calls_total);
Packit Service 82fcde
Packit Service 82fcde
  /* Do the real work.  */
Packit Service 82fcde
  result = (struct header *) (*reallocp)(real, len + sizeof (struct header));
Packit Service 82fcde
  if (result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      catomic_increment (&failed[idx_realloc]);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Record whether the reduction/increase happened in place.  */
Packit Service 82fcde
  if (real == result)
Packit Service 82fcde
    catomic_increment (&inplace);
Packit Service 82fcde
  /* Was the buffer increased?  */
Packit Service 82fcde
  if (old_len > len)
Packit Service 82fcde
    catomic_increment (&decreasing);
Packit Service 82fcde
Packit Service 82fcde
  /* Update the allocation data and write out the records if necessary.  */
Packit Service 82fcde
  update_data (result, len, old_len);
Packit Service 82fcde
Packit Service 82fcde
  /* Return the pointer to the user buffer.  */
Packit Service 82fcde
  return (void *) (result + 1);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `calloc' replacement.  We keep track of the memory usage if this is the
Packit Service 82fcde
   correct program.  */
Packit Service 82fcde
void *
Packit Service 82fcde
calloc (size_t n, size_t len)
Packit Service 82fcde
{
Packit Service 82fcde
  struct header *result;
Packit Service 82fcde
  size_t size = n * len;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If this is not the correct program just use the normal function.  */
Packit Service 82fcde
  if (not_me)
Packit Service 82fcde
    return (*callocp)(n, len);
Packit Service 82fcde
Packit Service 82fcde
  /* Keep track of number of calls.  */
Packit Service 82fcde
  catomic_increment (&calls[idx_calloc]);
Packit Service 82fcde
  /* Keep track of total memory consumption for `calloc'.  */
Packit Service 82fcde
  catomic_add (&total[idx_calloc], size);
Packit Service 82fcde
  /* Keep track of total memory requirement.  */
Packit Service 82fcde
  catomic_add (&grand_total, size);
Packit Service 82fcde
  /* Remember the size of the request.  */
Packit Service 82fcde
  if (size < 65536)
Packit Service 82fcde
    catomic_increment (&histogram[size / 16]);
Packit Service 82fcde
  else
Packit Service 82fcde
    catomic_increment (&large);
Packit Service 82fcde
  /* Total number of calls of any of the functions.  */
Packit Service 82fcde
  ++calls_total;
Packit Service 82fcde
Packit Service 82fcde
  /* Do the real work.  */
Packit Service 82fcde
  result = (struct header *) (*mallocp)(size + sizeof (struct header));
Packit Service 82fcde
  if (result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      catomic_increment (&failed[idx_calloc]);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Update the allocation data and write out the records if necessary.  */
Packit Service 82fcde
  update_data (result, size, 0);
Packit Service 82fcde
Packit Service 82fcde
  /* Do what `calloc' would have done and return the buffer to the caller.  */
Packit Service 82fcde
  return memset (result + 1, '\0', size);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `free' replacement.  We keep track of the memory usage if this is the
Packit Service 82fcde
   correct program.  */
Packit Service 82fcde
void
Packit Service 82fcde
free (void *ptr)
Packit Service 82fcde
{
Packit Service 82fcde
  struct header *real;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* If this is not the correct program just use the normal function.  */
Packit Service 82fcde
  if (not_me)
Packit Service 82fcde
    {
Packit Service 82fcde
      (*freep) (ptr);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* `free (NULL)' has no effect.  */
Packit Service 82fcde
  if (ptr == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      catomic_increment (&calls[idx_free]);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Determine the pointer to the header.  */
Packit Service 82fcde
  real = ((struct header *) ptr) - 1;
Packit Service 82fcde
  if (real->magic != MAGIC)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This block wasn't allocated here.  */
Packit Service 82fcde
      (*freep) (ptr);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Keep track of number of calls.  */
Packit Service 82fcde
  catomic_increment (&calls[idx_free]);
Packit Service 82fcde
  /* Keep track of total memory freed using `free'.  */
Packit Service 82fcde
  catomic_add (&total[idx_free], real->length);
Packit Service 82fcde
Packit Service 82fcde
  /* Update the allocation data and write out the records if necessary.  */
Packit Service 82fcde
  update_data (NULL, 0, real->length);
Packit Service 82fcde
Packit Service 82fcde
  /* Do the real work.  */
Packit Service 82fcde
  (*freep) (real);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `mmap' replacement.  We do not have to keep track of the size since
Packit Service 82fcde
   `munmap' will get it as a parameter.  */
Packit Service 82fcde
void *
Packit Service 82fcde
mmap (void *start, size_t len, int prot, int flags, int fd, off_t offset)
Packit Service 82fcde
{
Packit Service 82fcde
  void *result = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Always get a block.  We don't need extra memory.  */
Packit Service 82fcde
  result = (*mmapp)(start, len, prot, flags, fd, offset);
Packit Service 82fcde
Packit Service 82fcde
  if (!not_me && trace_mmap)
Packit Service 82fcde
    {
Packit Service 82fcde
      int idx = (flags & MAP_ANON
Packit Service 82fcde
                 ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
Packit Service 82fcde
Packit Service 82fcde
      /* Keep track of number of calls.  */
Packit Service 82fcde
      catomic_increment (&calls[idx]);
Packit Service 82fcde
      /* Keep track of total memory consumption for `malloc'.  */
Packit Service 82fcde
      catomic_add (&total[idx], len);
Packit Service 82fcde
      /* Keep track of total memory requirement.  */
Packit Service 82fcde
      catomic_add (&grand_total, len);
Packit Service 82fcde
      /* Remember the size of the request.  */
Packit Service 82fcde
      if (len < 65536)
Packit Service 82fcde
        catomic_increment (&histogram[len / 16]);
Packit Service 82fcde
      else
Packit Service 82fcde
        catomic_increment (&large);
Packit Service 82fcde
      /* Total number of calls of any of the functions.  */
Packit Service 82fcde
      catomic_increment (&calls_total);
Packit Service 82fcde
Packit Service 82fcde
      /* Check for failures.  */
Packit Service 82fcde
      if (result == NULL)
Packit Service 82fcde
        catomic_increment (&failed[idx]);
Packit Service 82fcde
      else if (idx == idx_mmap_w)
Packit Service 82fcde
        /* Update the allocation data and write out the records if
Packit Service 82fcde
           necessary.  Note the first parameter is NULL which means
Packit Service 82fcde
           the size is not tracked.  */
Packit Service 82fcde
        update_data (NULL, len, 0);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Return the pointer to the user buffer.  */
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `mmap64' replacement.  We do not have to keep track of the size since
Packit Service 82fcde
   `munmap' will get it as a parameter.  */
Packit Service 82fcde
void *
Packit Service 82fcde
mmap64 (void *start, size_t len, int prot, int flags, int fd, off64_t offset)
Packit Service 82fcde
{
Packit Service 82fcde
  void *result = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Always get a block.  We don't need extra memory.  */
Packit Service 82fcde
  result = (*mmap64p)(start, len, prot, flags, fd, offset);
Packit Service 82fcde
Packit Service 82fcde
  if (!not_me && trace_mmap)
Packit Service 82fcde
    {
Packit Service 82fcde
      int idx = (flags & MAP_ANON
Packit Service 82fcde
                 ? idx_mmap_a : prot & PROT_WRITE ? idx_mmap_w : idx_mmap_r);
Packit Service 82fcde
Packit Service 82fcde
      /* Keep track of number of calls.  */
Packit Service 82fcde
      catomic_increment (&calls[idx]);
Packit Service 82fcde
      /* Keep track of total memory consumption for `malloc'.  */
Packit Service 82fcde
      catomic_add (&total[idx], len);
Packit Service 82fcde
      /* Keep track of total memory requirement.  */
Packit Service 82fcde
      catomic_add (&grand_total, len);
Packit Service 82fcde
      /* Remember the size of the request.  */
Packit Service 82fcde
      if (len < 65536)
Packit Service 82fcde
        catomic_increment (&histogram[len / 16]);
Packit Service 82fcde
      else
Packit Service 82fcde
        catomic_increment (&large);
Packit Service 82fcde
      /* Total number of calls of any of the functions.  */
Packit Service 82fcde
      catomic_increment (&calls_total);
Packit Service 82fcde
Packit Service 82fcde
      /* Check for failures.  */
Packit Service 82fcde
      if (result == NULL)
Packit Service 82fcde
        catomic_increment (&failed[idx]);
Packit Service 82fcde
      else if (idx == idx_mmap_w)
Packit Service 82fcde
        /* Update the allocation data and write out the records if
Packit Service 82fcde
           necessary.  Note the first parameter is NULL which means
Packit Service 82fcde
           the size is not tracked.  */
Packit Service 82fcde
        update_data (NULL, len, 0);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Return the pointer to the user buffer.  */
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `mremap' replacement.  We do not have to keep track of the size since
Packit Service 82fcde
   `munmap' will get it as a parameter.  */
Packit Service 82fcde
void *
Packit Service 82fcde
mremap (void *start, size_t old_len, size_t len, int flags, ...)
Packit Service 82fcde
{
Packit Service 82fcde
  void *result = NULL;
Packit Service 82fcde
  va_list ap;
Packit Service 82fcde
Packit Service 82fcde
  va_start (ap, flags);
Packit Service 82fcde
  void *newaddr = (flags & MREMAP_FIXED) ? va_arg (ap, void *) : NULL;
Packit Service 82fcde
  va_end (ap);
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Always get a block.  We don't need extra memory.  */
Packit Service 82fcde
  result = (*mremapp)(start, old_len, len, flags, newaddr);
Packit Service 82fcde
Packit Service 82fcde
  if (!not_me && trace_mmap)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Keep track of number of calls.  */
Packit Service 82fcde
      catomic_increment (&calls[idx_mremap]);
Packit Service 82fcde
      if (len > old_len)
Packit Service 82fcde
        {
Packit Service 82fcde
          /* Keep track of total memory consumption for `malloc'.  */
Packit Service 82fcde
          catomic_add (&total[idx_mremap], len - old_len);
Packit Service 82fcde
          /* Keep track of total memory requirement.  */
Packit Service 82fcde
          catomic_add (&grand_total, len - old_len);
Packit Service 82fcde
        }
Packit Service 82fcde
      /* Remember the size of the request.  */
Packit Service 82fcde
      if (len < 65536)
Packit Service 82fcde
        catomic_increment (&histogram[len / 16]);
Packit Service 82fcde
      else
Packit Service 82fcde
        catomic_increment (&large);
Packit Service 82fcde
      /* Total number of calls of any of the functions.  */
Packit Service 82fcde
      catomic_increment (&calls_total);
Packit Service 82fcde
Packit Service 82fcde
      /* Check for failures.  */
Packit Service 82fcde
      if (result == NULL)
Packit Service 82fcde
        catomic_increment (&failed[idx_mremap]);
Packit Service 82fcde
      else
Packit Service 82fcde
        {
Packit Service 82fcde
          /* Record whether the reduction/increase happened in place.  */
Packit Service 82fcde
          if (start == result)
Packit Service 82fcde
            catomic_increment (&inplace_mremap);
Packit Service 82fcde
          /* Was the buffer increased?  */
Packit Service 82fcde
          if (old_len > len)
Packit Service 82fcde
            catomic_increment (&decreasing_mremap);
Packit Service 82fcde
Packit Service 82fcde
          /* Update the allocation data and write out the records if
Packit Service 82fcde
             necessary.  Note the first parameter is NULL which means
Packit Service 82fcde
             the size is not tracked.  */
Packit Service 82fcde
          update_data (NULL, len, old_len);
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Return the pointer to the user buffer.  */
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* `munmap' replacement.  */
Packit Service 82fcde
int
Packit Service 82fcde
munmap (void *start, size_t len)
Packit Service 82fcde
{
Packit Service 82fcde
  int result;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine real implementation if not already happened.  */
Packit Service 82fcde
  if (__glibc_unlikely (initialized <= 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (initialized == -1)
Packit Service 82fcde
        return -1;
Packit Service 82fcde
Packit Service 82fcde
      me ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Do the real work.  */
Packit Service 82fcde
  result = (*munmapp)(start, len);
Packit Service 82fcde
Packit Service 82fcde
  if (!not_me && trace_mmap)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Keep track of number of calls.  */
Packit Service 82fcde
      catomic_increment (&calls[idx_munmap]);
Packit Service 82fcde
Packit Service 82fcde
      if (__glibc_likely (result == 0))
Packit Service 82fcde
        {
Packit Service 82fcde
          /* Keep track of total memory freed using `free'.  */
Packit Service 82fcde
          catomic_add (&total[idx_munmap], len);
Packit Service 82fcde
Packit Service 82fcde
          /* Update the allocation data and write out the records if
Packit Service 82fcde
             necessary.  */
Packit Service 82fcde
          update_data (NULL, 0, len);
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        catomic_increment (&failed[idx_munmap]);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Write some statistics to standard error.  */
Packit Service 82fcde
static void
Packit Service 82fcde
__attribute__ ((destructor))
Packit Service 82fcde
dest (void)
Packit Service 82fcde
{
Packit Service 82fcde
  int percent, cnt;
Packit Service 82fcde
  unsigned long int maxcalls;
Packit Service 82fcde
Packit Service 82fcde
  /* If we haven't done anything here just return.  */
Packit Service 82fcde
  if (not_me)
Packit Service 82fcde
    return;
Packit Service 82fcde
Packit Service 82fcde
  /* If we should call any of the memory functions don't do any profiling.  */
Packit Service 82fcde
  not_me = true;
Packit Service 82fcde
Packit Service 82fcde
  /* Finish the output file.  */
Packit Service 82fcde
  if (fd != -1)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Write the partially filled buffer.  */
Packit Service 82fcde
      if (buffer_cnt > buffer_size)
Packit Service 82fcde
        write (fd, buffer + buffer_size,
Packit Service 82fcde
               (buffer_cnt - buffer_size) * sizeof (struct entry));
Packit Service 82fcde
      else
Packit Service 82fcde
        write (fd, buffer, buffer_cnt * sizeof (struct entry));
Packit Service 82fcde
Packit Service 82fcde
      /* Go back to the beginning of the file.  We allocated two records
Packit Service 82fcde
         here when we opened the file.  */
Packit Service 82fcde
      lseek (fd, 0, SEEK_SET);
Packit Service 82fcde
      /* Write out a record containing the total size.  */
Packit Service 82fcde
      first.stack = peak_total;
Packit Service 82fcde
      write (fd, &first, sizeof (struct entry));
Packit Service 82fcde
      /* Write out another record containing the maximum for heap and
Packit Service 82fcde
         stack.  */
Packit Service 82fcde
      first.heap = peak_heap;
Packit Service 82fcde
      first.stack = peak_stack;
Packit Service 82fcde
      GETTIME (first.time_low, first.time_high);
Packit Service 82fcde
      write (fd, &first, sizeof (struct entry));
Packit Service 82fcde
Packit Service 82fcde
      /* Close the file.  */
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      fd = -1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Write a colorful statistic.  */
Packit Service 82fcde
  fprintf (stderr, "\n\
Packit Service 82fcde
\e[01;32mMemory usage summary:\e[0;0m heap total: %llu, heap peak: %lu, stack peak: %lu\n\
Packit Service 82fcde
\e[04;34m         total calls   total memory   failed calls\e[0m\n\
Packit Service 82fcde
\e[00;34m malloc|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n\
Packit Service 82fcde
\e[00;34mrealloc|\e[0m %10lu   %12llu   %s%12lu\e[00;00m  (nomove:%ld, dec:%ld, free:%ld)\n\
Packit Service 82fcde
\e[00;34m calloc|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n\
Packit Service 82fcde
\e[00;34m   free|\e[0m %10lu   %12llu\n",
Packit Service 82fcde
           (unsigned long long int) grand_total, (unsigned long int) peak_heap,
Packit Service 82fcde
           (unsigned long int) peak_stack,
Packit Service 82fcde
           (unsigned long int) calls[idx_malloc],
Packit Service 82fcde
           (unsigned long long int) total[idx_malloc],
Packit Service 82fcde
           failed[idx_malloc] ? "\e[01;41m" : "",
Packit Service 82fcde
           (unsigned long int) failed[idx_malloc],
Packit Service 82fcde
           (unsigned long int) calls[idx_realloc],
Packit Service 82fcde
           (unsigned long long int) total[idx_realloc],
Packit Service 82fcde
           failed[idx_realloc] ? "\e[01;41m" : "",
Packit Service 82fcde
           (unsigned long int) failed[idx_realloc],
Packit Service 82fcde
           (unsigned long int) inplace,
Packit Service 82fcde
           (unsigned long int) decreasing,
Packit Service 82fcde
           (unsigned long int) realloc_free,
Packit Service 82fcde
           (unsigned long int) calls[idx_calloc],
Packit Service 82fcde
           (unsigned long long int) total[idx_calloc],
Packit Service 82fcde
           failed[idx_calloc] ? "\e[01;41m" : "",
Packit Service 82fcde
           (unsigned long int) failed[idx_calloc],
Packit Service 82fcde
           (unsigned long int) calls[idx_free],
Packit Service 82fcde
           (unsigned long long int) total[idx_free]);
Packit Service 82fcde
Packit Service 82fcde
  if (trace_mmap)
Packit Service 82fcde
    fprintf (stderr, "\
Packit Service 82fcde
\e[00;34mmmap(r)|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n\
Packit Service 82fcde
\e[00;34mmmap(w)|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n\
Packit Service 82fcde
\e[00;34mmmap(a)|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n\
Packit Service 82fcde
\e[00;34m mremap|\e[0m %10lu   %12llu   %s%12lu\e[00;00m  (nomove: %ld, dec:%ld)\n\
Packit Service 82fcde
\e[00;34m munmap|\e[0m %10lu   %12llu   %s%12lu\e[00;00m\n",
Packit Service 82fcde
             (unsigned long int) calls[idx_mmap_r],
Packit Service 82fcde
             (unsigned long long int) total[idx_mmap_r],
Packit Service 82fcde
             failed[idx_mmap_r] ? "\e[01;41m" : "",
Packit Service 82fcde
             (unsigned long int) failed[idx_mmap_r],
Packit Service 82fcde
             (unsigned long int) calls[idx_mmap_w],
Packit Service 82fcde
             (unsigned long long int) total[idx_mmap_w],
Packit Service 82fcde
             failed[idx_mmap_w] ? "\e[01;41m" : "",
Packit Service 82fcde
             (unsigned long int) failed[idx_mmap_w],
Packit Service 82fcde
             (unsigned long int) calls[idx_mmap_a],
Packit Service 82fcde
             (unsigned long long int) total[idx_mmap_a],
Packit Service 82fcde
             failed[idx_mmap_a] ? "\e[01;41m" : "",
Packit Service 82fcde
             (unsigned long int) failed[idx_mmap_a],
Packit Service 82fcde
             (unsigned long int) calls[idx_mremap],
Packit Service 82fcde
             (unsigned long long int) total[idx_mremap],
Packit Service 82fcde
             failed[idx_mremap] ? "\e[01;41m" : "",
Packit Service 82fcde
             (unsigned long int) failed[idx_mremap],
Packit Service 82fcde
             (unsigned long int) inplace_mremap,
Packit Service 82fcde
             (unsigned long int) decreasing_mremap,
Packit Service 82fcde
             (unsigned long int) calls[idx_munmap],
Packit Service 82fcde
             (unsigned long long int) total[idx_munmap],
Packit Service 82fcde
             failed[idx_munmap] ? "\e[01;41m" : "",
Packit Service 82fcde
             (unsigned long int) failed[idx_munmap]);
Packit Service 82fcde
Packit Service 82fcde
  /* Write out a histoogram of the sizes of the allocations.  */
Packit Service 82fcde
  fprintf (stderr, "\e[01;32mHistogram for block sizes:\e[0;0m\n");
Packit Service 82fcde
Packit Service 82fcde
  /* Determine the maximum of all calls for each size range.  */
Packit Service 82fcde
  maxcalls = large;
Packit Service 82fcde
  for (cnt = 0; cnt < 65536; cnt += 16)
Packit Service 82fcde
    if (histogram[cnt / 16] > maxcalls)
Packit Service 82fcde
      maxcalls = histogram[cnt / 16];
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = 0; cnt < 65536; cnt += 16)
Packit Service 82fcde
    /* Only write out the nonzero entries.  */
Packit Service 82fcde
    if (histogram[cnt / 16] != 0)
Packit Service 82fcde
      {
Packit Service 82fcde
        percent = (histogram[cnt / 16] * 100) / calls_total;
Packit Service 82fcde
        fprintf (stderr, "%5d-%-5d%12lu ", cnt, cnt + 15,
Packit Service 82fcde
                 (unsigned long int) histogram[cnt / 16]);
Packit Service 82fcde
        if (percent == 0)
Packit Service 82fcde
          fputs (" <1% \e[41;37m", stderr);
Packit Service 82fcde
        else
Packit Service 82fcde
          fprintf (stderr, "%3d%% \e[41;37m", percent);
Packit Service 82fcde
Packit Service 82fcde
        /* Draw a bar with a length corresponding to the current
Packit Service 82fcde
           percentage.  */
Packit Service 82fcde
        percent = (histogram[cnt / 16] * 50) / maxcalls;
Packit Service 82fcde
        while (percent-- > 0)
Packit Service 82fcde
          fputc ('=', stderr);
Packit Service 82fcde
        fputs ("\e[0;0m\n", stderr);
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
  if (large != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      percent = (large * 100) / calls_total;
Packit Service 82fcde
      fprintf (stderr, "   large   %12lu ", (unsigned long int) large);
Packit Service 82fcde
      if (percent == 0)
Packit Service 82fcde
        fputs (" <1% \e[41;37m", stderr);
Packit Service 82fcde
      else
Packit Service 82fcde
        fprintf (stderr, "%3d%% \e[41;37m", percent);
Packit Service 82fcde
      percent = (large * 50) / maxcalls;
Packit Service 82fcde
      while (percent-- > 0)
Packit Service 82fcde
        fputc ('=', stderr);
Packit Service 82fcde
      fputs ("\e[0;0m\n", stderr);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Any following malloc/free etc. calls should generate statistics again,
Packit Service 82fcde
     because otherwise freeing something that has been malloced before
Packit Service 82fcde
     this destructor (including struct header in front of it) wouldn't
Packit Service 82fcde
     be properly freed.  */
Packit Service 82fcde
  not_me = false;
Packit Service 82fcde
}