[lib/memory] Add mallinfo support

2006-02-15 Paul Jakma <paul.jakma@sun.com>

	* configure.ac: Check for mallinfo, being careful to link test
	  so we can detect things like umem being used (which doesn't
	  provide a mallinfo).
	* lib/memory.c: (mtype_memstr) new helper function to
	  return human friendly string for a byte count.
	  (mtype_stats_alloc) new function, for users to retrieve
	  number of objects allocated.
	  (show_memory_mallinfo) New function, show mallinfo statistics
	  if available.
	  (show_memory_all_cmd) Call show_memory_mallinfo, if mallinfo
	  is available.
	* lib/memory.h: Export mtype_memstr and mtype_stats_alloc.
	  Provide a define for a reasonable buffer size for
	  mtype_memstr.
This commit is contained in:
Paul Jakma 2006-03-30 13:53:59 +00:00
parent b5b628c1fa
commit 41be32bfe6
5 changed files with 161 additions and 2 deletions

View file

@ -1,3 +1,9 @@
2006-02-15 Paul Jakma <paul.jakma@sun.com>
* configure.ac: Check for mallinfo, being careful to link test
so we can detect things like umem being used (which doesn't
provide a mallinfo).
2006-01-31 Paul Jakma <paul.jakma@sun.com>
* configure.ac: Cleanup the hideous {net,ucd}-snmp section

View file

@ -5,7 +5,7 @@
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
##
## $Id: configure.ac,v 1.118 2006/01/31 10:09:27 paul Exp $
## $Id: configure.ac,v 1.119 2006/03/30 13:53:59 paul Exp $
AC_PREREQ(2.53)
AC_INIT(Quagga, 0.99.3, [http://bugzilla.quagga.net])
@ -1236,6 +1236,24 @@ if test x"${ac_cv_header_execinfo_h}" = x"yes"; then
)
fi
dnl -----------------------------------------
dnl check for malloc mallinfo struct and call
dnl this must try and link using LIBS, in
dnl order to check no alternative allocator
dnl has been specified, which might not provide
dnl mallinfo, e.g. such as Umem on Solaris.
dnl -----------------------------------------
AC_CHECK_HEADERS(malloc.h,
[AC_MSG_CHECKING(whether mallinfo is available)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
[[struct mallinfo ac_x; ac_x = mallinfo ();]])],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_MALLINFO,,mallinfo)],
AC_MSG_RESULT(no)
)
]
)
dnl ----------
dnl configure date
dnl ----------

View file

@ -1,3 +1,17 @@
2006-03-15 Paul Jakma <paul.jakma@sun.com>
* memory.c: (mtype_memstr) new helper function to
return human friendly string for a byte count.
(mtype_stats_alloc) new function, for users to retrieve
number of objects allocated.
(show_memory_mallinfo) New function, show mallinfo statistics
if available.
(show_memory_all_cmd) Call show_memory_mallinfo, if mallinfo
is available.
* memory.h: Export mtype_memstr and mtype_stats_alloc.
Provide a define for a reasonable buffer size for
mtype_memstr.
2006-03-14 Paul Jakma <paul.jakma@sun.com>
* privs.c: (zprivs_caps_init) Change user IDs before lowering

View file

@ -21,6 +21,7 @@
*/
#include <zebra.h>
#include <malloc.h>
#include "log.h"
#include "memory.h"
@ -278,6 +279,47 @@ show_memory_vty (struct vty *vty, struct memory_list *list)
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_all,
show_memory_all_cmd,
"show memory all",
@ -287,7 +329,11 @@ DEFUN (show_memory_all,
{
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)
@ -416,3 +462,72 @@ memory_init (void)
install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
install_element (ENABLE_NODE, &show_memory_isis_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 t, g, m, k;
/* easy cases */
if (!bytes)
return "0 bytes";
if (bytes == 1)
return "1 byte";
if (sizeof (unsigned long) >= 8)
/* Hacked to make it not warn on ILP32 machines
* Shift will always be 40 at runtime. See below too */
t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0);
else
t = 0;
g = bytes >> 30;
m = bytes >> 20;
k = bytes >> 10;
if (t > 10)
{
/* The shift will always be 39 at runtime.
* Just hacked to make it not warn on 'smaller' machines.
* Static compiler analysis should mean no extra code
*/
if (bytes & (1 << (sizeof (unsigned long) >= 8 ? 39 : 0)))
t++;
snprintf (buf, len, "%4d TiB", t);
}
else if (g > 10)
{
if (bytes & (1 << 29))
g++;
snprintf (buf, len, "%d GiB", g);
}
else 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;
}

View file

@ -79,4 +79,10 @@ extern char *mtype_zstrdup (const char *file, int line, int type,
const char *str);
extern void memory_init (void);
/* 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 */