Annotation of embedaddon/quagga/lib/memory.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Memory management routine
        !             3:  * Copyright (C) 1998 Kunihiro Ishiguro
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: /* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
        !            25: #if !defined(HAVE_STDLIB_H) || (defined(GNU_LINUX) && defined(HAVE_MALLINFO))
        !            26: #include <malloc.h>
        !            27: #endif /* !HAVE_STDLIB_H || HAVE_MALLINFO */
        !            28: 
        !            29: #include "log.h"
        !            30: #include "memory.h"
        !            31: 
        !            32: static void alloc_inc (int);
        !            33: static void alloc_dec (int);
        !            34: static void log_memstats(int log_priority);
        !            35: 
        !            36: static const struct message mstr [] =
        !            37: {
        !            38:   { MTYPE_THREAD, "thread" },
        !            39:   { MTYPE_THREAD_MASTER, "thread_master" },
        !            40:   { MTYPE_VECTOR, "vector" },
        !            41:   { MTYPE_VECTOR_INDEX, "vector_index" },
        !            42:   { MTYPE_IF, "interface" },
        !            43:   { 0, NULL },
        !            44: };
        !            45: 
        !            46: /* Fatal memory allocation error occured. */
        !            47: static void __attribute__ ((noreturn))
        !            48: zerror (const char *fname, int type, size_t size)
        !            49: {
        !            50:   zlog_err ("%s : can't allocate memory for `%s' size %d: %s\n", 
        !            51:            fname, lookup (mstr, type), (int) size, safe_strerror(errno));
        !            52:   log_memstats(LOG_WARNING);
        !            53:   /* N.B. It might be preferable to call zlog_backtrace_sigsafe here, since
        !            54:      that function should definitely be safe in an OOM condition.  But
        !            55:      unfortunately zlog_backtrace_sigsafe does not support syslog logging at
        !            56:      this time... */
        !            57:   zlog_backtrace(LOG_WARNING);
        !            58:   abort();
        !            59: }
        !            60: 
        !            61: /*
        !            62:  * Allocate memory of a given size, to be tracked by a given type.
        !            63:  * Effects: Returns a pointer to usable memory.  If memory cannot
        !            64:  * be allocated, aborts execution.
        !            65:  */
        !            66: void *
        !            67: zmalloc (int type, size_t size)
        !            68: {
        !            69:   void *memory;
        !            70: 
        !            71:   memory = malloc (size);
        !            72: 
        !            73:   if (memory == NULL)
        !            74:     zerror ("malloc", type, size);
        !            75: 
        !            76:   alloc_inc (type);
        !            77: 
        !            78:   return memory;
        !            79: }
        !            80: 
        !            81: /*
        !            82:  * Allocate memory as in zmalloc, and also clear the memory.
        !            83:  */
        !            84: void *
        !            85: zcalloc (int type, size_t size)
        !            86: {
        !            87:   void *memory;
        !            88: 
        !            89:   memory = calloc (1, size);
        !            90: 
        !            91:   if (memory == NULL)
        !            92:     zerror ("calloc", type, size);
        !            93: 
        !            94:   alloc_inc (type);
        !            95: 
        !            96:   return memory;
        !            97: }
        !            98: 
        !            99: /* 
        !           100:  * Given a pointer returned by zmalloc or zcalloc, free it and
        !           101:  * return a pointer to a new size, basically acting like realloc().
        !           102:  * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the
        !           103:  * same type.
        !           104:  * Effects: Returns a pointer to the new memory, or aborts.
        !           105:  */
        !           106: void *
        !           107: zrealloc (int type, void *ptr, size_t size)
        !           108: {
        !           109:   void *memory;
        !           110: 
        !           111:   memory = realloc (ptr, size);
        !           112:   if (memory == NULL)
        !           113:     zerror ("realloc", type, size);
        !           114:   if (ptr == NULL)
        !           115:     alloc_inc (type);
        !           116: 
        !           117:   return memory;
        !           118: }
        !           119: 
        !           120: /*
        !           121:  * Free memory allocated by z*alloc or zstrdup.
        !           122:  * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the
        !           123:  * same type.
        !           124:  * Effects: The memory is freed and may no longer be referenced.
        !           125:  */
        !           126: void
        !           127: zfree (int type, void *ptr)
        !           128: {
        !           129:   if (ptr != NULL)
        !           130:     {
        !           131:       alloc_dec (type);
        !           132:       free (ptr);
        !           133:     }
        !           134: }
        !           135: 
        !           136: /*
        !           137:  * Duplicate a string, counting memory usage by type.
        !           138:  * Effects: The string is duplicated, and the return value must
        !           139:  * eventually be passed to zfree with the same type.  The function will
        !           140:  * succeed or abort.
        !           141:  */
        !           142: char *
        !           143: zstrdup (int type, const char *str)
        !           144: {
        !           145:   void *dup;
        !           146: 
        !           147:   dup = strdup (str);
        !           148:   if (dup == NULL)
        !           149:     zerror ("strdup", type, strlen (str));
        !           150:   alloc_inc (type);
        !           151:   return dup;
        !           152: }
        !           153: 
        !           154: #ifdef MEMORY_LOG
        !           155: static struct 
        !           156: {
        !           157:   const char *name;
        !           158:   long alloc;
        !           159:   unsigned long t_malloc;
        !           160:   unsigned long c_malloc;
        !           161:   unsigned long t_calloc;
        !           162:   unsigned long c_calloc;
        !           163:   unsigned long t_realloc;
        !           164:   unsigned long t_free;
        !           165:   unsigned long c_strdup;
        !           166: } mstat [MTYPE_MAX];
        !           167: 
        !           168: static void
        !           169: mtype_log (char *func, void *memory, const char *file, int line, int type)
        !           170: {
        !           171:   zlog_debug ("%s: %s %p %s %d", func, lookup (mstr, type), memory, file, line);
        !           172: }
        !           173: 
        !           174: void *
        !           175: mtype_zmalloc (const char *file, int line, int type, size_t size)
        !           176: {
        !           177:   void *memory;
        !           178: 
        !           179:   mstat[type].c_malloc++;
        !           180:   mstat[type].t_malloc++;
        !           181: 
        !           182:   memory = zmalloc (type, size);
        !           183:   mtype_log ("zmalloc", memory, file, line, type);
        !           184: 
        !           185:   return memory;
        !           186: }
        !           187: 
        !           188: void *
        !           189: mtype_zcalloc (const char *file, int line, int type, size_t size)
        !           190: {
        !           191:   void *memory;
        !           192: 
        !           193:   mstat[type].c_calloc++;
        !           194:   mstat[type].t_calloc++;
        !           195: 
        !           196:   memory = zcalloc (type, size);
        !           197:   mtype_log ("xcalloc", memory, file, line, type);
        !           198: 
        !           199:   return memory;
        !           200: }
        !           201: 
        !           202: void *
        !           203: mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t size)
        !           204: {
        !           205:   void *memory;
        !           206: 
        !           207:   /* Realloc need before allocated pointer. */
        !           208:   mstat[type].t_realloc++;
        !           209: 
        !           210:   memory = zrealloc (type, ptr, size);
        !           211: 
        !           212:   mtype_log ("xrealloc", memory, file, line, type);
        !           213: 
        !           214:   return memory;
        !           215: }
        !           216: 
        !           217: /* Important function. */
        !           218: void 
        !           219: mtype_zfree (const char *file, int line, int type, void *ptr)
        !           220: {
        !           221:   mstat[type].t_free++;
        !           222: 
        !           223:   mtype_log ("xfree", ptr, file, line, type);
        !           224: 
        !           225:   zfree (type, ptr);
        !           226: }
        !           227: 
        !           228: char *
        !           229: mtype_zstrdup (const char *file, int line, int type, const char *str)
        !           230: {
        !           231:   char *memory;
        !           232: 
        !           233:   mstat[type].c_strdup++;
        !           234: 
        !           235:   memory = zstrdup (type, str);
        !           236:   
        !           237:   mtype_log ("xstrdup", memory, file, line, type);
        !           238: 
        !           239:   return memory;
        !           240: }
        !           241: #else
        !           242: static struct 
        !           243: {
        !           244:   char *name;
        !           245:   long alloc;
        !           246: } mstat [MTYPE_MAX];
        !           247: #endif /* MEMORY_LOG */
        !           248: 
        !           249: /* Increment allocation counter. */
        !           250: static void
        !           251: alloc_inc (int type)
        !           252: {
        !           253:   mstat[type].alloc++;
        !           254: }
        !           255: 
        !           256: /* Decrement allocation counter. */
        !           257: static void
        !           258: alloc_dec (int type)
        !           259: {
        !           260:   mstat[type].alloc--;
        !           261: }
        !           262: 
        !           263: /* Looking up memory status from vty interface. */
        !           264: #include "vector.h"
        !           265: #include "vty.h"
        !           266: #include "command.h"
        !           267: 
        !           268: static void
        !           269: log_memstats(int pri)
        !           270: {
        !           271:   struct mlist *ml;
        !           272: 
        !           273:   for (ml = mlists; ml->list; ml++)
        !           274:     {
        !           275:       struct memory_list *m;
        !           276: 
        !           277:       zlog (NULL, pri, "Memory utilization in module %s:", ml->name);
        !           278:       for (m = ml->list; m->index >= 0; m++)
        !           279:        if (m->index && mstat[m->index].alloc)
        !           280:          zlog (NULL, pri, "  %-30s: %10ld", m->format, mstat[m->index].alloc);
        !           281:     }
        !           282: }
        !           283: 
        !           284: void
        !           285: log_memstats_stderr (const char *prefix)
        !           286: {
        !           287:   struct mlist *ml;
        !           288:   struct memory_list *m;
        !           289:   int i;
        !           290:   int j = 0;
        !           291: 
        !           292:   for (ml = mlists; ml->list; ml++)
        !           293:     {
        !           294:       i = 0;
        !           295: 
        !           296:       for (m = ml->list; m->index >= 0; m++)
        !           297:         if (m->index && mstat[m->index].alloc)
        !           298:           {
        !           299:             if (!i)
        !           300:               fprintf (stderr,
        !           301:                        "%s: memstats: Current memory utilization in module %s:\n",
        !           302:                        prefix,
        !           303:                        ml->name);
        !           304:             fprintf (stderr,
        !           305:                      "%s: memstats:  %-30s: %10ld%s\n",
        !           306:                      prefix,
        !           307:                      m->format,
        !           308:                      mstat[m->index].alloc,
        !           309:                      mstat[m->index].alloc < 0 ? " (REPORT THIS BUG!)" : "");
        !           310:             i = j = 1;
        !           311:           }
        !           312:     }
        !           313: 
        !           314:   if (j)
        !           315:     fprintf (stderr,
        !           316:              "%s: memstats: NOTE: If configuration exists, utilization may be "
        !           317:              "expected.\n",
        !           318:              prefix);
        !           319:   else
        !           320:     fprintf (stderr,
        !           321:              "%s: memstats: No remaining tracked memory utilization.\n",
        !           322:              prefix);
        !           323: }
        !           324: 
        !           325: static void
        !           326: show_separator(struct vty *vty)
        !           327: {
        !           328:   vty_out (vty, "-----------------------------\r\n");
        !           329: }
        !           330: 
        !           331: static int
        !           332: show_memory_vty (struct vty *vty, struct memory_list *list)
        !           333: {
        !           334:   struct memory_list *m;
        !           335:   int needsep = 0;
        !           336: 
        !           337:   for (m = list; m->index >= 0; m++)
        !           338:     if (m->index == 0)
        !           339:       {
        !           340:        if (needsep)
        !           341:          {
        !           342:            show_separator (vty);
        !           343:            needsep = 0;
        !           344:          }
        !           345:       }
        !           346:     else if (mstat[m->index].alloc)
        !           347:       {
        !           348:        vty_out (vty, "%-30s: %10ld\r\n", m->format, mstat[m->index].alloc);
        !           349:        needsep = 1;
        !           350:       }
        !           351:   return needsep;
        !           352: }
        !           353: 
        !           354: #ifdef HAVE_MALLINFO
        !           355: static int
        !           356: show_memory_mallinfo (struct vty *vty)
        !           357: {
        !           358:   struct mallinfo minfo = mallinfo();
        !           359:   char buf[MTYPE_MEMSTR_LEN];
        !           360:   
        !           361:   vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE);
        !           362:   vty_out (vty, "  Total heap allocated:  %s%s",
        !           363:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena),
        !           364:            VTY_NEWLINE);
        !           365:   vty_out (vty, "  Holding block headers: %s%s",
        !           366:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd),
        !           367:            VTY_NEWLINE);
        !           368:   vty_out (vty, "  Used small blocks:     %s%s",
        !           369:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks),
        !           370:            VTY_NEWLINE);
        !           371:   vty_out (vty, "  Used ordinary blocks:  %s%s",
        !           372:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks),
        !           373:            VTY_NEWLINE);
        !           374:   vty_out (vty, "  Free small blocks:     %s%s",
        !           375:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks),
        !           376:            VTY_NEWLINE);
        !           377:   vty_out (vty, "  Free ordinary blocks:  %s%s",
        !           378:            mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks),
        !           379:            VTY_NEWLINE);
        !           380:   vty_out (vty, "  Ordinary blocks:       %ld%s",
        !           381:            (unsigned long)minfo.ordblks,
        !           382:            VTY_NEWLINE);
        !           383:   vty_out (vty, "  Small blocks:          %ld%s",
        !           384:            (unsigned long)minfo.smblks,
        !           385:            VTY_NEWLINE);
        !           386:   vty_out (vty, "  Holding blocks:        %ld%s",
        !           387:            (unsigned long)minfo.hblks,
        !           388:            VTY_NEWLINE);
        !           389:   vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s",
        !           390:            VTY_NEWLINE);
        !           391:   return 1;
        !           392: }
        !           393: #endif /* HAVE_MALLINFO */
        !           394: 
        !           395: DEFUN (show_memory_all,
        !           396:        show_memory_all_cmd,
        !           397:        "show memory all",
        !           398:        "Show running system information\n"
        !           399:        "Memory statistics\n"
        !           400:        "All memory statistics\n")
        !           401: {
        !           402:   struct mlist *ml;
        !           403:   int needsep = 0;
        !           404:   
        !           405: #ifdef HAVE_MALLINFO
        !           406:   needsep = show_memory_mallinfo (vty);
        !           407: #endif /* HAVE_MALLINFO */
        !           408:   
        !           409:   for (ml = mlists; ml->list; ml++)
        !           410:     {
        !           411:       if (needsep)
        !           412:        show_separator (vty);
        !           413:       needsep = show_memory_vty (vty, ml->list);
        !           414:     }
        !           415: 
        !           416:   return CMD_SUCCESS;
        !           417: }
        !           418: 
        !           419: ALIAS (show_memory_all,
        !           420:        show_memory_cmd,
        !           421:        "show memory",
        !           422:        "Show running system information\n"
        !           423:        "Memory statistics\n")
        !           424: 
        !           425: DEFUN (show_memory_lib,
        !           426:        show_memory_lib_cmd,
        !           427:        "show memory lib",
        !           428:        SHOW_STR
        !           429:        "Memory statistics\n"
        !           430:        "Library memory\n")
        !           431: {
        !           432:   show_memory_vty (vty, memory_list_lib);
        !           433:   return CMD_SUCCESS;
        !           434: }
        !           435: 
        !           436: DEFUN (show_memory_zebra,
        !           437:        show_memory_zebra_cmd,
        !           438:        "show memory zebra",
        !           439:        SHOW_STR
        !           440:        "Memory statistics\n"
        !           441:        "Zebra memory\n")
        !           442: {
        !           443:   show_memory_vty (vty, memory_list_zebra);
        !           444:   return CMD_SUCCESS;
        !           445: }
        !           446: 
        !           447: DEFUN (show_memory_rip,
        !           448:        show_memory_rip_cmd,
        !           449:        "show memory rip",
        !           450:        SHOW_STR
        !           451:        "Memory statistics\n"
        !           452:        "RIP memory\n")
        !           453: {
        !           454:   show_memory_vty (vty, memory_list_rip);
        !           455:   return CMD_SUCCESS;
        !           456: }
        !           457: 
        !           458: DEFUN (show_memory_ripng,
        !           459:        show_memory_ripng_cmd,
        !           460:        "show memory ripng",
        !           461:        SHOW_STR
        !           462:        "Memory statistics\n"
        !           463:        "RIPng memory\n")
        !           464: {
        !           465:   show_memory_vty (vty, memory_list_ripng);
        !           466:   return CMD_SUCCESS;
        !           467: }
        !           468: 
        !           469: DEFUN (show_memory_bgp,
        !           470:        show_memory_bgp_cmd,
        !           471:        "show memory bgp",
        !           472:        SHOW_STR
        !           473:        "Memory statistics\n"
        !           474:        "BGP memory\n")
        !           475: {
        !           476:   show_memory_vty (vty, memory_list_bgp);
        !           477:   return CMD_SUCCESS;
        !           478: }
        !           479: 
        !           480: DEFUN (show_memory_ospf,
        !           481:        show_memory_ospf_cmd,
        !           482:        "show memory ospf",
        !           483:        SHOW_STR
        !           484:        "Memory statistics\n"
        !           485:        "OSPF memory\n")
        !           486: {
        !           487:   show_memory_vty (vty, memory_list_ospf);
        !           488:   return CMD_SUCCESS;
        !           489: }
        !           490: 
        !           491: DEFUN (show_memory_ospf6,
        !           492:        show_memory_ospf6_cmd,
        !           493:        "show memory ospf6",
        !           494:        SHOW_STR
        !           495:        "Memory statistics\n"
        !           496:        "OSPF6 memory\n")
        !           497: {
        !           498:   show_memory_vty (vty, memory_list_ospf6);
        !           499:   return CMD_SUCCESS;
        !           500: }
        !           501: 
        !           502: DEFUN (show_memory_isis,
        !           503:        show_memory_isis_cmd,
        !           504:        "show memory isis",
        !           505:        SHOW_STR
        !           506:        "Memory statistics\n"
        !           507:        "ISIS memory\n")
        !           508: {
        !           509:   show_memory_vty (vty, memory_list_isis);
        !           510:   return CMD_SUCCESS;
        !           511: }
        !           512: 
        !           513: void
        !           514: memory_init (void)
        !           515: {
        !           516:   install_element (RESTRICTED_NODE, &show_memory_cmd);
        !           517:   install_element (RESTRICTED_NODE, &show_memory_all_cmd);
        !           518:   install_element (RESTRICTED_NODE, &show_memory_lib_cmd);
        !           519:   install_element (RESTRICTED_NODE, &show_memory_rip_cmd);
        !           520:   install_element (RESTRICTED_NODE, &show_memory_ripng_cmd);
        !           521:   install_element (RESTRICTED_NODE, &show_memory_bgp_cmd);
        !           522:   install_element (RESTRICTED_NODE, &show_memory_ospf_cmd);
        !           523:   install_element (RESTRICTED_NODE, &show_memory_ospf6_cmd);
        !           524:   install_element (RESTRICTED_NODE, &show_memory_isis_cmd);
        !           525: 
        !           526:   install_element (VIEW_NODE, &show_memory_cmd);
        !           527:   install_element (VIEW_NODE, &show_memory_all_cmd);
        !           528:   install_element (VIEW_NODE, &show_memory_lib_cmd);
        !           529:   install_element (VIEW_NODE, &show_memory_rip_cmd);
        !           530:   install_element (VIEW_NODE, &show_memory_ripng_cmd);
        !           531:   install_element (VIEW_NODE, &show_memory_bgp_cmd);
        !           532:   install_element (VIEW_NODE, &show_memory_ospf_cmd);
        !           533:   install_element (VIEW_NODE, &show_memory_ospf6_cmd);
        !           534:   install_element (VIEW_NODE, &show_memory_isis_cmd);
        !           535: 
        !           536:   install_element (ENABLE_NODE, &show_memory_cmd);
        !           537:   install_element (ENABLE_NODE, &show_memory_all_cmd);
        !           538:   install_element (ENABLE_NODE, &show_memory_lib_cmd);
        !           539:   install_element (ENABLE_NODE, &show_memory_zebra_cmd);
        !           540:   install_element (ENABLE_NODE, &show_memory_rip_cmd);
        !           541:   install_element (ENABLE_NODE, &show_memory_ripng_cmd);
        !           542:   install_element (ENABLE_NODE, &show_memory_bgp_cmd);
        !           543:   install_element (ENABLE_NODE, &show_memory_ospf_cmd);
        !           544:   install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
        !           545:   install_element (ENABLE_NODE, &show_memory_isis_cmd);
        !           546: }
        !           547: 
        !           548: /* Stats querying from users */
        !           549: /* Return a pointer to a human friendly string describing
        !           550:  * the byte count passed in. E.g:
        !           551:  * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
        !           552:  * Up to 4 significant figures will be given.
        !           553:  * The pointer returned may be NULL (indicating an error)
        !           554:  * or point to the given buffer, or point to static storage.
        !           555:  */
        !           556: const char *
        !           557: mtype_memstr (char *buf, size_t len, unsigned long bytes)
        !           558: {
        !           559:   unsigned int t, g, m, k;
        !           560:   
        !           561:   /* easy cases */
        !           562:   if (!bytes)
        !           563:     return "0 bytes";
        !           564:   if (bytes == 1)
        !           565:     return "1 byte";
        !           566:     
        !           567:   if (sizeof (unsigned long) >= 8)
        !           568:     /* Hacked to make it not warn on ILP32 machines
        !           569:      * Shift will always be 40 at runtime. See below too */
        !           570:     t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0);
        !           571:   else
        !           572:     t = 0;
        !           573:   g = bytes >> 30;
        !           574:   m = bytes >> 20;
        !           575:   k = bytes >> 10;
        !           576:   
        !           577:   if (t > 10)
        !           578:     {
        !           579:       /* The shift will always be 39 at runtime.
        !           580:        * Just hacked to make it not warn on 'smaller' machines. 
        !           581:        * Static compiler analysis should mean no extra code
        !           582:        */
        !           583:       if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0)))
        !           584:         t++;
        !           585:       snprintf (buf, len, "%4d TiB", t);
        !           586:     }
        !           587:   else if (g > 10)
        !           588:     {
        !           589:       if (bytes & (1 << 29))
        !           590:         g++;
        !           591:       snprintf (buf, len, "%d GiB", g);
        !           592:     }
        !           593:   else if (m > 10)
        !           594:     {
        !           595:       if (bytes & (1 << 19))
        !           596:         m++;
        !           597:       snprintf (buf, len, "%d MiB", m);
        !           598:     }
        !           599:   else if (k > 10)
        !           600:     {
        !           601:       if (bytes & (1 << 9))
        !           602:         k++;
        !           603:       snprintf (buf, len, "%d KiB", k);
        !           604:     }
        !           605:   else
        !           606:     snprintf (buf, len, "%ld bytes", bytes);
        !           607:   
        !           608:   return buf;
        !           609: }
        !           610: 
        !           611: unsigned long
        !           612: mtype_stats_alloc (int type)
        !           613: {
        !           614:   return mstat[type].alloc;
        !           615: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>