forked from Mirror/frr
[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:
parent
b5b628c1fa
commit
41be32bfe6
|
@ -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
|
||||
|
|
20
configure.ac
20
configure.ac
|
@ -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 ----------
|
||||
|
|
|
@ -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
|
||||
|
|
117
lib/memory.c
117
lib/memory.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue