Acked-by: Donald Sharp <[email protected]> On Wed, Feb 24, 2016 at 12:26 AM, David Lamparter < [email protected]> wrote:
> The following commit will recreate memory.[ch]. > > Signed-off-by: David Lamparter <[email protected]> > --- > lib/Makefile.am | 8 +- > lib/memory.c | 486 > ------------------------------------------------------- > lib/memory.h | 98 +---------- > lib/memory_vty.c | 486 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/memory_vty.h | 96 +++++++++++ > 5 files changed, 589 insertions(+), 585 deletions(-) > delete mode 100644 lib/memory.c > create mode 100644 lib/memory_vty.c > create mode 100644 lib/memory_vty.h > > diff --git a/lib/Makefile.am b/lib/Makefile.am > index 6b107f4..2093f30 100644 > --- a/lib/Makefile.am > +++ b/lib/Makefile.am > @@ -10,10 +10,11 @@ libzebra_la_LDFLAGS = -version-info 0:0:0 > libzebra_la_SOURCES = \ > network.c pid_output.c getopt.c getopt1.c daemon.c \ > checksum.c vector.c linklist.c vty.c command.c \ > - sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c > hash.c \ > + sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \ > filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ > zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c > keychain.c privs.c \ > - sigevent.c pqueue.c jhash.c memtypes.c workqueue.c vrf.c > + sigevent.c pqueue.c jhash.c memtypes.c workqueue.c vrf.c \ > + memory_vty.c > > BUILT_SOURCES = memtypes.h route_types.h gitversion.h > > @@ -28,7 +29,8 @@ pkginclude_HEADERS = \ > str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \ > plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ > privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ > - workqueue.h route_types.h libospf.h vrf.h > + workqueue.h route_types.h libospf.h vrf.h \ > + memory_vty.h > > noinst_HEADERS = \ > plist_int.h > diff --git a/lib/memory.c b/lib/memory.c > deleted file mode 100644 > index 269520d..0000000 > --- a/lib/memory.c > +++ /dev/null > @@ -1,486 +0,0 @@ > -/* > - * Memory management routine > - * Copyright (C) 1998 Kunihiro Ishiguro > - * > - * This file is part of GNU Zebra. > - * > - * GNU Zebra is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License as published by the > - * Free Software Foundation; either version 2, or (at your option) any > - * later version. > - * > - * GNU Zebra is distributed in the hope that it will be useful, but > - * WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - * General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with GNU Zebra; see the file COPYING. If not, write to the Free > - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA > - * 02111-1307, USA. > - */ > - > -#include <zebra.h> > -/* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */ > -#if !defined(HAVE_STDLIB_H) || (defined(GNU_LINUX) && > defined(HAVE_MALLINFO)) > -#include <malloc.h> > -#endif /* !HAVE_STDLIB_H || HAVE_MALLINFO */ > - > -#include "log.h" > -#include "memory.h" > - > -static void alloc_inc (int); > -static void alloc_dec (int); > -static void log_memstats(int log_priority); > - > -static const struct message mstr [] = > -{ > - { MTYPE_THREAD, "thread" }, > - { MTYPE_THREAD_MASTER, "thread_master" }, > - { MTYPE_VECTOR, "vector" }, > - { MTYPE_VECTOR_INDEX, "vector_index" }, > - { MTYPE_IF, "interface" }, > - { 0, NULL }, > -}; > - > -/* Fatal memory allocation error occured. */ > -static void __attribute__ ((noreturn)) > -zerror (const char *fname, int type, size_t size) > -{ > - zlog_err ("%s : can't allocate memory for `%s' size %d: %s\n", > - fname, lookup (mstr, type), (int) size, safe_strerror(errno)); > - log_memstats(LOG_WARNING); > - /* N.B. It might be preferable to call zlog_backtrace_sigsafe here, > since > - that function should definitely be safe in an OOM condition. But > - unfortunately zlog_backtrace_sigsafe does not support syslog logging > at > - this time... */ > - zlog_backtrace(LOG_WARNING); > - abort(); > -} > - > -/* > - * Allocate memory of a given size, to be tracked by a given type. > - * Effects: Returns a pointer to usable memory. If memory cannot > - * be allocated, aborts execution. > - */ > -void * > -zmalloc (int type, size_t size) > -{ > - void *memory; > - > - memory = malloc (size); > - > - if (memory == NULL) > - zerror ("malloc", type, size); > - > - alloc_inc (type); > - > - return memory; > -} > - > -/* > - * Allocate memory as in zmalloc, and also clear the memory. > - */ > -void * > -zcalloc (int type, size_t size) > -{ > - void *memory; > - > - memory = calloc (1, size); > - > - if (memory == NULL) > - zerror ("calloc", type, size); > - > - alloc_inc (type); > - > - return memory; > -} > - > -/* > - * Given a pointer returned by zmalloc or zcalloc, free it and > - * return a pointer to a new size, basically acting like realloc(). > - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the > - * same type. > - * Effects: Returns a pointer to the new memory, or aborts. > - */ > -void * > -zrealloc (int type, void *ptr, size_t size) > -{ > - void *memory; > - > - if (ptr == NULL) /* is really alloc */ > - return zcalloc(type, size); > - > - memory = realloc (ptr, size); > - if (memory == NULL) > - zerror ("realloc", type, size); > - if (ptr == NULL) > - alloc_inc (type); > - > - return memory; > -} > - > -/* > - * Free memory allocated by z*alloc or zstrdup. > - * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the > - * same type. > - * Effects: The memory is freed and may no longer be referenced. > - */ > -void > -zfree (int type, void *ptr) > -{ > - if (ptr != NULL) > - { > - alloc_dec (type); > - free (ptr); > - } > -} > - > -/* > - * Duplicate a string, counting memory usage by type. > - * Effects: The string is duplicated, and the return value must > - * eventually be passed to zfree with the same type. The function will > - * succeed or abort. > - */ > -char * > -zstrdup (int type, const char *str) > -{ > - void *dup; > - > - dup = strdup (str); > - if (dup == NULL) > - zerror ("strdup", type, strlen (str)); > - alloc_inc (type); > - return dup; > -} > - > -#ifdef MEMORY_LOG > -static struct > -{ > - const char *name; > - long alloc; > - unsigned long t_malloc; > - unsigned long c_malloc; > - unsigned long t_calloc; > - unsigned long c_calloc; > - unsigned long t_realloc; > - unsigned long t_free; > - unsigned long c_strdup; > -} mstat [MTYPE_MAX]; > - > -static void > -mtype_log (char *func, void *memory, const char *file, int line, int type) > -{ > - zlog_debug ("%s: %s %p %s %d", func, lookup (mstr, type), memory, file, > line); > -} > - > -void * > -mtype_zmalloc (const char *file, int line, int type, size_t size) > -{ > - void *memory; > - > - mstat[type].c_malloc++; > - mstat[type].t_malloc++; > - > - memory = zmalloc (type, size); > - mtype_log ("zmalloc", memory, file, line, type); > - > - return memory; > -} > - > -void * > -mtype_zcalloc (const char *file, int line, int type, size_t size) > -{ > - void *memory; > - > - mstat[type].c_calloc++; > - mstat[type].t_calloc++; > - > - memory = zcalloc (type, size); > - mtype_log ("xcalloc", memory, file, line, type); > - > - return memory; > -} > - > -void * > -mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t > size) > -{ > - void *memory; > - > - /* Realloc need before allocated pointer. */ > - mstat[type].t_realloc++; > - > - memory = zrealloc (type, ptr, size); > - > - mtype_log ("xrealloc", memory, file, line, type); > - > - return memory; > -} > - > -/* Important function. */ > -void > -mtype_zfree (const char *file, int line, int type, void *ptr) > -{ > - mstat[type].t_free++; > - > - mtype_log ("xfree", ptr, file, line, type); > - > - zfree (type, ptr); > -} > - > -char * > -mtype_zstrdup (const char *file, int line, int type, const char *str) > -{ > - char *memory; > - > - mstat[type].c_strdup++; > - > - memory = zstrdup (type, str); > - > - mtype_log ("xstrdup", memory, file, line, type); > - > - return memory; > -} > -#else > -static struct > -{ > - char *name; > - long alloc; > -} mstat [MTYPE_MAX]; > -#endif /* MEMORY_LOG */ > - > -/* Increment allocation counter. */ > -static void > -alloc_inc (int type) > -{ > - mstat[type].alloc++; > -} > - > -/* Decrement allocation counter. */ > -static void > -alloc_dec (int type) > -{ > - mstat[type].alloc--; > -} > - > -/* Looking up memory status from vty interface. */ > -#include "vector.h" > -#include "vty.h" > -#include "command.h" > - > -static void > -log_memstats(int pri) > -{ > - struct mlist *ml; > - > - for (ml = mlists; ml->list; ml++) > - { > - struct memory_list *m; > - > - zlog (NULL, pri, "Memory utilization in module %s:", ml->name); > - for (m = ml->list; m->index >= 0; m++) > - if (m->index && mstat[m->index].alloc) > - zlog (NULL, pri, " %-30s: %10ld", m->format, > mstat[m->index].alloc); > - } > -} > - > -void > -log_memstats_stderr (const char *prefix) > -{ > - struct mlist *ml; > - struct memory_list *m; > - int i; > - int j = 0; > - > - for (ml = mlists; ml->list; ml++) > - { > - i = 0; > - > - for (m = ml->list; m->index >= 0; m++) > - if (m->index && mstat[m->index].alloc) > - { > - if (!i) > - fprintf (stderr, > - "%s: memstats: Current memory utilization in > module %s:\n", > - prefix, > - ml->name); > - fprintf (stderr, > - "%s: memstats: %-30s: %10ld%s\n", > - prefix, > - m->format, > - mstat[m->index].alloc, > - mstat[m->index].alloc < 0 ? " (REPORT THIS BUG!)" : > ""); > - i = j = 1; > - } > - } > - > - if (j) > - fprintf (stderr, > - "%s: memstats: NOTE: If configuration exists, utilization > may be " > - "expected.\n", > - prefix); > - else > - fprintf (stderr, > - "%s: memstats: No remaining tracked memory utilization.\n", > - prefix); > -} > - > -static void > -show_separator(struct vty *vty) > -{ > - vty_out (vty, "-----------------------------\r\n"); > -} > - > -static int > -show_memory_vty (struct vty *vty, struct memory_list *list) > -{ > - struct memory_list *m; > - int needsep = 0; > - > - for (m = list; m->index >= 0; m++) > - if (m->index == 0) > - { > - if (needsep) > - { > - show_separator (vty); > - needsep = 0; > - } > - } > - else if (mstat[m->index].alloc) > - { > - vty_out (vty, "%-30s: %10ld\r\n", m->format, > mstat[m->index].alloc); > - needsep = 1; > - } > - return needsep; > -} > - > -#ifdef HAVE_MALLINFO > -static int > -show_memory_mallinfo (struct vty *vty) > -{ > - struct mallinfo minfo = mallinfo(); > - char buf[MTYPE_MEMSTR_LEN]; > - > - vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE); > - vty_out (vty, " Total heap allocated: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena), > - VTY_NEWLINE); > - vty_out (vty, " Holding block headers: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd), > - VTY_NEWLINE); > - vty_out (vty, " Used small blocks: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks), > - VTY_NEWLINE); > - vty_out (vty, " Used ordinary blocks: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks), > - VTY_NEWLINE); > - vty_out (vty, " Free small blocks: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks), > - VTY_NEWLINE); > - vty_out (vty, " Free ordinary blocks: %s%s", > - mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks), > - VTY_NEWLINE); > - vty_out (vty, " Ordinary blocks: %ld%s", > - (unsigned long)minfo.ordblks, > - VTY_NEWLINE); > - vty_out (vty, " Small blocks: %ld%s", > - (unsigned long)minfo.smblks, > - VTY_NEWLINE); > - vty_out (vty, " Holding blocks: %ld%s", > - (unsigned long)minfo.hblks, > - VTY_NEWLINE); > - vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s", > - VTY_NEWLINE); > - return 1; > -} > -#endif /* HAVE_MALLINFO */ > - > -DEFUN (show_memory, > - show_memory_cmd, > - "show memory", > - "Show running system information\n" > - "Memory statistics\n") > -{ > - struct mlist *ml; > - int needsep = 0; > - > -#ifdef HAVE_MALLINFO > - needsep = show_memory_mallinfo (vty); > -#endif /* HAVE_MALLINFO */ > - > - for (ml = mlists; ml->list; ml++) > - { > - if (needsep) > - show_separator (vty); > - needsep = show_memory_vty (vty, ml->list); > - } > - > - return CMD_SUCCESS; > -} > - > - > -void > -memory_init (void) > -{ > - install_element (RESTRICTED_NODE, &show_memory_cmd); > - > - install_element (VIEW_NODE, &show_memory_cmd); > - > - install_element (ENABLE_NODE, &show_memory_cmd); > -} > - > -/* Stats querying from users */ > -/* Return a pointer to a human friendly string describing > - * the byte count passed in. E.g: > - * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc. > - * Up to 4 significant figures will be given. > - * The pointer returned may be NULL (indicating an error) > - * or point to the given buffer, or point to static storage. > - */ > -const char * > -mtype_memstr (char *buf, size_t len, unsigned long bytes) > -{ > - unsigned int m, k; > - > - /* easy cases */ > - if (!bytes) > - return "0 bytes"; > - if (bytes == 1) > - return "1 byte"; > - > - /* > - * When we pass the 2gb barrier mallinfo() can no longer report > - * correct data so it just does something odd... > - * Reporting like Terrabytes of data. Which makes users... > - * edgy.. yes edgy that's the term for it. > - * So let's just give up gracefully > - */ > - if (bytes > 0x7fffffff) > - return "> 2GB"; > - > - m = bytes >> 20; > - k = bytes >> 10; > - > - if (m > 10) > - { > - if (bytes & (1 << 19)) > - m++; > - snprintf (buf, len, "%d MiB", m); > - } > - else if (k > 10) > - { > - if (bytes & (1 << 9)) > - k++; > - snprintf (buf, len, "%d KiB", k); > - } > - else > - snprintf (buf, len, "%ld bytes", bytes); > - > - return buf; > -} > - > -unsigned long > -mtype_stats_alloc (int type) > -{ > - return mstat[type].alloc; > -} > diff --git a/lib/memory.h b/lib/memory.h > index 2396223..15bf280 100644 > --- a/lib/memory.h > +++ b/lib/memory.h > @@ -1,96 +1,2 @@ > -/* Memory management routine > - Copyright (C) 1998 Kunihiro Ishiguro > - > -This file is part of GNU Zebra. > - > -GNU Zebra is free software; you can redistribute it and/or modify it > -under the terms of the GNU General Public License as published by the > -Free Software Foundation; either version 2, or (at your option) any > -later version. > - > -GNU Zebra is distributed in the hope that it will be useful, but > -WITHOUT ANY WARRANTY; without even the implied warranty of > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > -General Public License for more details. > - > -You should have received a copy of the GNU General Public License > -along with GNU Zebra; see the file COPYING. If not, write to the Free > -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA > -02111-1307, USA. */ > - > -#ifndef _ZEBRA_MEMORY_H > -#define _ZEBRA_MEMORY_H > - > -#define array_size(ar) (sizeof(ar) / sizeof(ar[0])) > - > -/* For pretty printing of memory allocate information. */ > -struct memory_list > -{ > - int index; > - const char *format; > -}; > - > -struct mlist { > - struct memory_list *list; > - const char *name; > -}; > - > -#include "lib/memtypes.h" > - > -extern struct mlist mlists[]; > - > -/* #define MEMORY_LOG */ > -#ifdef MEMORY_LOG > -#define XMALLOC(mtype, size) \ > - mtype_zmalloc (__FILE__, __LINE__, (mtype), (size)) > -#define XCALLOC(mtype, size) \ > - mtype_zcalloc (__FILE__, __LINE__, (mtype), (size)) > -#define XREALLOC(mtype, ptr, size) \ > - mtype_zrealloc (__FILE__, __LINE__, (mtype), (ptr), (size)) > -#define XFREE(mtype, ptr) \ > - do { \ > - mtype_zfree (__FILE__, __LINE__, (mtype), (ptr)); \ > - ptr = NULL; } \ > - while (0) > -#define XSTRDUP(mtype, str) \ > - mtype_zstrdup (__FILE__, __LINE__, (mtype), (str)) > -#else > -#define XMALLOC(mtype, size) zmalloc ((mtype), (size)) > -#define XCALLOC(mtype, size) zcalloc ((mtype), (size)) > -#define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size)) > -#define XFREE(mtype, ptr) do { \ > - zfree ((mtype), (ptr)); \ > - ptr = NULL; } \ > - while (0) > -#define XSTRDUP(mtype, str) zstrdup ((mtype), (str)) > -#endif /* MEMORY_LOG */ > - > -/* Prototypes of memory function. */ > -extern void *zmalloc (int type, size_t size); > -extern void *zcalloc (int type, size_t size); > -extern void *zrealloc (int type, void *ptr, size_t size); > -extern void zfree (int type, void *ptr); > -extern char *zstrdup (int type, const char *str); > - > -extern void *mtype_zmalloc (const char *file, int line, int type, size_t > size); > - > -extern void *mtype_zcalloc (const char *file, int line, int type, size_t > size); > - > -extern void *mtype_zrealloc (const char *file, int line, int type, void > *ptr, > - size_t size); > - > -extern void mtype_zfree (const char *file, int line, int type, > - void *ptr); > - > -extern char *mtype_zstrdup (const char *file, int line, int type, > - const char *str); > -extern void memory_init (void); > -extern void log_memstats_stderr (const char *); > - > -/* return number of allocations outstanding for the type */ > -extern unsigned long mtype_stats_alloc (int); > - > -/* Human friendly string for given byte count */ > -#define MTYPE_MEMSTR_LEN 20 > -extern const char *mtype_memstr (char *, size_t, unsigned long); > -#endif /* _ZEBRA_MEMORY_H */ > +/* temporary */ > +#include "memory_vty.h" > diff --git a/lib/memory_vty.c b/lib/memory_vty.c > new file mode 100644 > index 0000000..269520d > --- /dev/null > +++ b/lib/memory_vty.c > @@ -0,0 +1,486 @@ > +/* > + * Memory management routine > + * Copyright (C) 1998 Kunihiro Ishiguro > + * > + * This file is part of GNU Zebra. > + * > + * GNU Zebra is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2, or (at your option) any > + * later version. > + * > + * GNU Zebra is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GNU Zebra; see the file COPYING. If not, write to the Free > + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA > + * 02111-1307, USA. > + */ > + > +#include <zebra.h> > +/* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */ > +#if !defined(HAVE_STDLIB_H) || (defined(GNU_LINUX) && > defined(HAVE_MALLINFO)) > +#include <malloc.h> > +#endif /* !HAVE_STDLIB_H || HAVE_MALLINFO */ > + > +#include "log.h" > +#include "memory.h" > + > +static void alloc_inc (int); > +static void alloc_dec (int); > +static void log_memstats(int log_priority); > + > +static const struct message mstr [] = > +{ > + { MTYPE_THREAD, "thread" }, > + { MTYPE_THREAD_MASTER, "thread_master" }, > + { MTYPE_VECTOR, "vector" }, > + { MTYPE_VECTOR_INDEX, "vector_index" }, > + { MTYPE_IF, "interface" }, > + { 0, NULL }, > +}; > + > +/* Fatal memory allocation error occured. */ > +static void __attribute__ ((noreturn)) > +zerror (const char *fname, int type, size_t size) > +{ > + zlog_err ("%s : can't allocate memory for `%s' size %d: %s\n", > + fname, lookup (mstr, type), (int) size, safe_strerror(errno)); > + log_memstats(LOG_WARNING); > + /* N.B. It might be preferable to call zlog_backtrace_sigsafe here, > since > + that function should definitely be safe in an OOM condition. But > + unfortunately zlog_backtrace_sigsafe does not support syslog logging > at > + this time... */ > + zlog_backtrace(LOG_WARNING); > + abort(); > +} > + > +/* > + * Allocate memory of a given size, to be tracked by a given type. > + * Effects: Returns a pointer to usable memory. If memory cannot > + * be allocated, aborts execution. > + */ > +void * > +zmalloc (int type, size_t size) > +{ > + void *memory; > + > + memory = malloc (size); > + > + if (memory == NULL) > + zerror ("malloc", type, size); > + > + alloc_inc (type); > + > + return memory; > +} > + > +/* > + * Allocate memory as in zmalloc, and also clear the memory. > + */ > +void * > +zcalloc (int type, size_t size) > +{ > + void *memory; > + > + memory = calloc (1, size); > + > + if (memory == NULL) > + zerror ("calloc", type, size); > + > + alloc_inc (type); > + > + return memory; > +} > + > +/* > + * Given a pointer returned by zmalloc or zcalloc, free it and > + * return a pointer to a new size, basically acting like realloc(). > + * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the > + * same type. > + * Effects: Returns a pointer to the new memory, or aborts. > + */ > +void * > +zrealloc (int type, void *ptr, size_t size) > +{ > + void *memory; > + > + if (ptr == NULL) /* is really alloc */ > + return zcalloc(type, size); > + > + memory = realloc (ptr, size); > + if (memory == NULL) > + zerror ("realloc", type, size); > + if (ptr == NULL) > + alloc_inc (type); > + > + return memory; > +} > + > +/* > + * Free memory allocated by z*alloc or zstrdup. > + * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the > + * same type. > + * Effects: The memory is freed and may no longer be referenced. > + */ > +void > +zfree (int type, void *ptr) > +{ > + if (ptr != NULL) > + { > + alloc_dec (type); > + free (ptr); > + } > +} > + > +/* > + * Duplicate a string, counting memory usage by type. > + * Effects: The string is duplicated, and the return value must > + * eventually be passed to zfree with the same type. The function will > + * succeed or abort. > + */ > +char * > +zstrdup (int type, const char *str) > +{ > + void *dup; > + > + dup = strdup (str); > + if (dup == NULL) > + zerror ("strdup", type, strlen (str)); > + alloc_inc (type); > + return dup; > +} > + > +#ifdef MEMORY_LOG > +static struct > +{ > + const char *name; > + long alloc; > + unsigned long t_malloc; > + unsigned long c_malloc; > + unsigned long t_calloc; > + unsigned long c_calloc; > + unsigned long t_realloc; > + unsigned long t_free; > + unsigned long c_strdup; > +} mstat [MTYPE_MAX]; > + > +static void > +mtype_log (char *func, void *memory, const char *file, int line, int type) > +{ > + zlog_debug ("%s: %s %p %s %d", func, lookup (mstr, type), memory, file, > line); > +} > + > +void * > +mtype_zmalloc (const char *file, int line, int type, size_t size) > +{ > + void *memory; > + > + mstat[type].c_malloc++; > + mstat[type].t_malloc++; > + > + memory = zmalloc (type, size); > + mtype_log ("zmalloc", memory, file, line, type); > + > + return memory; > +} > + > +void * > +mtype_zcalloc (const char *file, int line, int type, size_t size) > +{ > + void *memory; > + > + mstat[type].c_calloc++; > + mstat[type].t_calloc++; > + > + memory = zcalloc (type, size); > + mtype_log ("xcalloc", memory, file, line, type); > + > + return memory; > +} > + > +void * > +mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t > size) > +{ > + void *memory; > + > + /* Realloc need before allocated pointer. */ > + mstat[type].t_realloc++; > + > + memory = zrealloc (type, ptr, size); > + > + mtype_log ("xrealloc", memory, file, line, type); > + > + return memory; > +} > + > +/* Important function. */ > +void > +mtype_zfree (const char *file, int line, int type, void *ptr) > +{ > + mstat[type].t_free++; > + > + mtype_log ("xfree", ptr, file, line, type); > + > + zfree (type, ptr); > +} > + > +char * > +mtype_zstrdup (const char *file, int line, int type, const char *str) > +{ > + char *memory; > + > + mstat[type].c_strdup++; > + > + memory = zstrdup (type, str); > + > + mtype_log ("xstrdup", memory, file, line, type); > + > + return memory; > +} > +#else > +static struct > +{ > + char *name; > + long alloc; > +} mstat [MTYPE_MAX]; > +#endif /* MEMORY_LOG */ > + > +/* Increment allocation counter. */ > +static void > +alloc_inc (int type) > +{ > + mstat[type].alloc++; > +} > + > +/* Decrement allocation counter. */ > +static void > +alloc_dec (int type) > +{ > + mstat[type].alloc--; > +} > + > +/* Looking up memory status from vty interface. */ > +#include "vector.h" > +#include "vty.h" > +#include "command.h" > + > +static void > +log_memstats(int pri) > +{ > + struct mlist *ml; > + > + for (ml = mlists; ml->list; ml++) > + { > + struct memory_list *m; > + > + zlog (NULL, pri, "Memory utilization in module %s:", ml->name); > + for (m = ml->list; m->index >= 0; m++) > + if (m->index && mstat[m->index].alloc) > + zlog (NULL, pri, " %-30s: %10ld", m->format, > mstat[m->index].alloc); > + } > +} > + > +void > +log_memstats_stderr (const char *prefix) > +{ > + struct mlist *ml; > + struct memory_list *m; > + int i; > + int j = 0; > + > + for (ml = mlists; ml->list; ml++) > + { > + i = 0; > + > + for (m = ml->list; m->index >= 0; m++) > + if (m->index && mstat[m->index].alloc) > + { > + if (!i) > + fprintf (stderr, > + "%s: memstats: Current memory utilization in > module %s:\n", > + prefix, > + ml->name); > + fprintf (stderr, > + "%s: memstats: %-30s: %10ld%s\n", > + prefix, > + m->format, > + mstat[m->index].alloc, > + mstat[m->index].alloc < 0 ? " (REPORT THIS BUG!)" : > ""); > + i = j = 1; > + } > + } > + > + if (j) > + fprintf (stderr, > + "%s: memstats: NOTE: If configuration exists, utilization > may be " > + "expected.\n", > + prefix); > + else > + fprintf (stderr, > + "%s: memstats: No remaining tracked memory utilization.\n", > + prefix); > +} > + > +static void > +show_separator(struct vty *vty) > +{ > + vty_out (vty, "-----------------------------\r\n"); > +} > + > +static int > +show_memory_vty (struct vty *vty, struct memory_list *list) > +{ > + struct memory_list *m; > + int needsep = 0; > + > + for (m = list; m->index >= 0; m++) > + if (m->index == 0) > + { > + if (needsep) > + { > + show_separator (vty); > + needsep = 0; > + } > + } > + else if (mstat[m->index].alloc) > + { > + vty_out (vty, "%-30s: %10ld\r\n", m->format, > mstat[m->index].alloc); > + needsep = 1; > + } > + return needsep; > +} > + > +#ifdef HAVE_MALLINFO > +static int > +show_memory_mallinfo (struct vty *vty) > +{ > + struct mallinfo minfo = mallinfo(); > + char buf[MTYPE_MEMSTR_LEN]; > + > + vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE); > + vty_out (vty, " Total heap allocated: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena), > + VTY_NEWLINE); > + vty_out (vty, " Holding block headers: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd), > + VTY_NEWLINE); > + vty_out (vty, " Used small blocks: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks), > + VTY_NEWLINE); > + vty_out (vty, " Used ordinary blocks: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks), > + VTY_NEWLINE); > + vty_out (vty, " Free small blocks: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks), > + VTY_NEWLINE); > + vty_out (vty, " Free ordinary blocks: %s%s", > + mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks), > + VTY_NEWLINE); > + vty_out (vty, " Ordinary blocks: %ld%s", > + (unsigned long)minfo.ordblks, > + VTY_NEWLINE); > + vty_out (vty, " Small blocks: %ld%s", > + (unsigned long)minfo.smblks, > + VTY_NEWLINE); > + vty_out (vty, " Holding blocks: %ld%s", > + (unsigned long)minfo.hblks, > + VTY_NEWLINE); > + vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s", > + VTY_NEWLINE); > + return 1; > +} > +#endif /* HAVE_MALLINFO */ > + > +DEFUN (show_memory, > + show_memory_cmd, > + "show memory", > + "Show running system information\n" > + "Memory statistics\n") > +{ > + struct mlist *ml; > + int needsep = 0; > + > +#ifdef HAVE_MALLINFO > + needsep = show_memory_mallinfo (vty); > +#endif /* HAVE_MALLINFO */ > + > + for (ml = mlists; ml->list; ml++) > + { > + if (needsep) > + show_separator (vty); > + needsep = show_memory_vty (vty, ml->list); > + } > + > + return CMD_SUCCESS; > +} > + > + > +void > +memory_init (void) > +{ > + install_element (RESTRICTED_NODE, &show_memory_cmd); > + > + install_element (VIEW_NODE, &show_memory_cmd); > + > + install_element (ENABLE_NODE, &show_memory_cmd); > +} > + > +/* Stats querying from users */ > +/* Return a pointer to a human friendly string describing > + * the byte count passed in. E.g: > + * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc. > + * Up to 4 significant figures will be given. > + * The pointer returned may be NULL (indicating an error) > + * or point to the given buffer, or point to static storage. > + */ > +const char * > +mtype_memstr (char *buf, size_t len, unsigned long bytes) > +{ > + unsigned int m, k; > + > + /* easy cases */ > + if (!bytes) > + return "0 bytes"; > + if (bytes == 1) > + return "1 byte"; > + > + /* > + * When we pass the 2gb barrier mallinfo() can no longer report > + * correct data so it just does something odd... > + * Reporting like Terrabytes of data. Which makes users... > + * edgy.. yes edgy that's the term for it. > + * So let's just give up gracefully > + */ > + if (bytes > 0x7fffffff) > + return "> 2GB"; > + > + m = bytes >> 20; > + k = bytes >> 10; > + > + if (m > 10) > + { > + if (bytes & (1 << 19)) > + m++; > + snprintf (buf, len, "%d MiB", m); > + } > + else if (k > 10) > + { > + if (bytes & (1 << 9)) > + k++; > + snprintf (buf, len, "%d KiB", k); > + } > + else > + snprintf (buf, len, "%ld bytes", bytes); > + > + return buf; > +} > + > +unsigned long > +mtype_stats_alloc (int type) > +{ > + return mstat[type].alloc; > +} > diff --git a/lib/memory_vty.h b/lib/memory_vty.h > new file mode 100644 > index 0000000..a0c47a9 > --- /dev/null > +++ b/lib/memory_vty.h > @@ -0,0 +1,96 @@ > +/* Memory management routine > + Copyright (C) 1998 Kunihiro Ishiguro > + > +This file is part of GNU Zebra. > + > +GNU Zebra is free software; you can redistribute it and/or modify it > +under the terms of the GNU General Public License as published by the > +Free Software Foundation; either version 2, or (at your option) any > +later version. > + > +GNU Zebra is distributed in the hope that it will be useful, but > +WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GNU Zebra; see the file COPYING. If not, write to the Free > +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA > +02111-1307, USA. */ > + > +#ifndef _ZEBRA_MEMORY_CLI_H > +#define _ZEBRA_MEMORY_CLI_H > + > +#define array_size(ar) (sizeof(ar) / sizeof(ar[0])) > + > +/* For pretty printing of memory allocate information. */ > +struct memory_list > +{ > + int index; > + const char *format; > +}; > + > +struct mlist { > + struct memory_list *list; > + const char *name; > +}; > + > +#include "lib/memtypes.h" > + > +extern struct mlist mlists[]; > + > +/* #define MEMORY_LOG */ > +#ifdef MEMORY_LOG > +#define XMALLOC(mtype, size) \ > + mtype_zmalloc (__FILE__, __LINE__, (mtype), (size)) > +#define XCALLOC(mtype, size) \ > + mtype_zcalloc (__FILE__, __LINE__, (mtype), (size)) > +#define XREALLOC(mtype, ptr, size) \ > + mtype_zrealloc (__FILE__, __LINE__, (mtype), (ptr), (size)) > +#define XFREE(mtype, ptr) \ > + do { \ > + mtype_zfree (__FILE__, __LINE__, (mtype), (ptr)); \ > + ptr = NULL; } \ > + while (0) > +#define XSTRDUP(mtype, str) \ > + mtype_zstrdup (__FILE__, __LINE__, (mtype), (str)) > +#else > +#define XMALLOC(mtype, size) zmalloc ((mtype), (size)) > +#define XCALLOC(mtype, size) zcalloc ((mtype), (size)) > +#define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size)) > +#define XFREE(mtype, ptr) do { \ > + zfree ((mtype), (ptr)); \ > + ptr = NULL; } \ > + while (0) > +#define XSTRDUP(mtype, str) zstrdup ((mtype), (str)) > +#endif /* MEMORY_LOG */ > + > +/* Prototypes of memory function. */ > +extern void *zmalloc (int type, size_t size); > +extern void *zcalloc (int type, size_t size); > +extern void *zrealloc (int type, void *ptr, size_t size); > +extern void zfree (int type, void *ptr); > +extern char *zstrdup (int type, const char *str); > + > +extern void *mtype_zmalloc (const char *file, int line, int type, size_t > size); > + > +extern void *mtype_zcalloc (const char *file, int line, int type, size_t > size); > + > +extern void *mtype_zrealloc (const char *file, int line, int type, void > *ptr, > + size_t size); > + > +extern void mtype_zfree (const char *file, int line, int type, > + void *ptr); > + > +extern char *mtype_zstrdup (const char *file, int line, int type, > + const char *str); > +extern void memory_init (void); > +extern void log_memstats_stderr (const char *); > + > +/* return number of allocations outstanding for the type */ > +extern unsigned long mtype_stats_alloc (int); > + > +/* Human friendly string for given byte count */ > +#define MTYPE_MEMSTR_LEN 20 > +extern const char *mtype_memstr (char *, size_t, unsigned long); > +#endif /* _ZEBRA_MEMORY_CLI_H */ > -- > 2.3.6 > > > _______________________________________________ > Quagga-dev mailing list > [email protected] > https://lists.quagga.net/mailman/listinfo/quagga-dev >
_______________________________________________ Quagga-dev mailing list [email protected] https://lists.quagga.net/mailman/listinfo/quagga-dev
