blob: 28bbdc11995db2573dcf67078203a7c388e52593 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Memory management routine
3 * Copyright (C) 1998 Kunihiro Ishiguro
Everton Marques871dbcf2009-08-11 15:43:05 -03004 * Portions Copyright (c) 2008 Everton da Silva Marques <everton.marques@gmail.com>
paul718e3742002-12-13 20:15:29 +00005 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24#include <zebra.h>
Paul Jakmad09552d2006-05-28 08:15:46 +000025/* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
Paul Jakma74176d22006-06-30 16:49:02 +000026#if !defined(HAVE_STDLIB_H) || (defined(GNU_LINUX) && defined(HAVE_MALLINFO))
Paul Jakma41be32b2006-03-30 13:53:59 +000027#include <malloc.h>
Paul Jakmad09552d2006-05-28 08:15:46 +000028#endif /* !HAVE_STDLIB_H || HAVE_MALLINFO */
paul718e3742002-12-13 20:15:29 +000029
30#include "log.h"
31#include "memory.h"
32
ajsf858e492004-11-16 14:25:30 +000033static void alloc_inc (int);
34static void alloc_dec (int);
ajs7fa25ff2004-11-15 16:12:32 +000035static void log_memstats(int log_priority);
David Lamparter6b0655a2014-06-04 06:53:35 +020036
Stephen Hemminger1423c802008-08-14 17:59:25 +010037static const struct message mstr [] =
paul718e3742002-12-13 20:15:29 +000038{
39 { MTYPE_THREAD, "thread" },
40 { MTYPE_THREAD_MASTER, "thread_master" },
41 { MTYPE_VECTOR, "vector" },
42 { MTYPE_VECTOR_INDEX, "vector_index" },
43 { MTYPE_IF, "interface" },
44 { 0, NULL },
45};
David Lamparter6b0655a2014-06-04 06:53:35 +020046
paul718e3742002-12-13 20:15:29 +000047/* Fatal memory allocation error occured. */
paul8cc41982005-05-06 21:25:49 +000048static void __attribute__ ((noreturn))
paul718e3742002-12-13 20:15:29 +000049zerror (const char *fname, int type, size_t size)
50{
ajs7fa25ff2004-11-15 16:12:32 +000051 zlog_err ("%s : can't allocate memory for `%s' size %d: %s\n",
ajs6099b3b2004-11-20 02:06:59 +000052 fname, lookup (mstr, type), (int) size, safe_strerror(errno));
ajs7fa25ff2004-11-15 16:12:32 +000053 log_memstats(LOG_WARNING);
ajs48d6c692004-11-26 20:52:59 +000054 /* N.B. It might be preferable to call zlog_backtrace_sigsafe here, since
ajs063ee522004-11-26 18:11:14 +000055 that function should definitely be safe in an OOM condition. But
ajs48d6c692004-11-26 20:52:59 +000056 unfortunately zlog_backtrace_sigsafe does not support syslog logging at
ajs063ee522004-11-26 18:11:14 +000057 this time... */
58 zlog_backtrace(LOG_WARNING);
ajs7fa25ff2004-11-15 16:12:32 +000059 abort();
paul718e3742002-12-13 20:15:29 +000060}
61
Greg Troxelb1679382010-09-17 12:19:13 -040062/*
63 * Allocate memory of a given size, to be tracked by a given type.
64 * Effects: Returns a pointer to usable memory. If memory cannot
65 * be allocated, aborts execution.
66 */
paul718e3742002-12-13 20:15:29 +000067void *
68zmalloc (int type, size_t size)
69{
70 void *memory;
71
72 memory = malloc (size);
73
74 if (memory == NULL)
75 zerror ("malloc", type, size);
76
77 alloc_inc (type);
78
79 return memory;
80}
81
Greg Troxelb1679382010-09-17 12:19:13 -040082/*
83 * Allocate memory as in zmalloc, and also clear the memory.
84 */
paul718e3742002-12-13 20:15:29 +000085void *
86zcalloc (int type, size_t size)
87{
88 void *memory;
89
90 memory = calloc (1, size);
91
92 if (memory == NULL)
93 zerror ("calloc", type, size);
94
95 alloc_inc (type);
96
97 return memory;
98}
99
Greg Troxelb1679382010-09-17 12:19:13 -0400100/*
101 * Given a pointer returned by zmalloc or zcalloc, free it and
102 * return a pointer to a new size, basically acting like realloc().
103 * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the
104 * same type.
105 * Effects: Returns a pointer to the new memory, or aborts.
106 */
paul718e3742002-12-13 20:15:29 +0000107void *
108zrealloc (int type, void *ptr, size_t size)
109{
110 void *memory;
111
112 memory = realloc (ptr, size);
113 if (memory == NULL)
114 zerror ("realloc", type, size);
Chris Hallcca85d22010-07-23 11:27:11 -0700115 if (ptr == NULL)
116 alloc_inc (type);
117
paul718e3742002-12-13 20:15:29 +0000118 return memory;
119}
120
Greg Troxelb1679382010-09-17 12:19:13 -0400121/*
122 * Free memory allocated by z*alloc or zstrdup.
123 * Requires: ptr was returned by zmalloc, zcalloc, or zrealloc with the
124 * same type.
125 * Effects: The memory is freed and may no longer be referenced.
126 */
paul718e3742002-12-13 20:15:29 +0000127void
128zfree (int type, void *ptr)
129{
Chris Hallcca85d22010-07-23 11:27:11 -0700130 if (ptr != NULL)
131 {
132 alloc_dec (type);
133 free (ptr);
134 }
paul718e3742002-12-13 20:15:29 +0000135}
136
Greg Troxelb1679382010-09-17 12:19:13 -0400137/*
138 * Duplicate a string, counting memory usage by type.
139 * Effects: The string is duplicated, and the return value must
140 * eventually be passed to zfree with the same type. The function will
141 * succeed or abort.
142 */
paul718e3742002-12-13 20:15:29 +0000143char *
hassob04c6992004-10-04 19:10:31 +0000144zstrdup (int type, const char *str)
paul718e3742002-12-13 20:15:29 +0000145{
146 void *dup;
147
148 dup = strdup (str);
149 if (dup == NULL)
150 zerror ("strdup", type, strlen (str));
151 alloc_inc (type);
152 return dup;
153}
David Lamparter6b0655a2014-06-04 06:53:35 +0200154
paul718e3742002-12-13 20:15:29 +0000155#ifdef MEMORY_LOG
ajsf858e492004-11-16 14:25:30 +0000156static struct
paul718e3742002-12-13 20:15:29 +0000157{
hassob04c6992004-10-04 19:10:31 +0000158 const char *name;
Chris Caputo228da422009-07-18 05:44:03 +0000159 long alloc;
paul718e3742002-12-13 20:15:29 +0000160 unsigned long t_malloc;
161 unsigned long c_malloc;
162 unsigned long t_calloc;
163 unsigned long c_calloc;
164 unsigned long t_realloc;
165 unsigned long t_free;
166 unsigned long c_strdup;
167} mstat [MTYPE_MAX];
168
ajsf858e492004-11-16 14:25:30 +0000169static void
paul718e3742002-12-13 20:15:29 +0000170mtype_log (char *func, void *memory, const char *file, int line, int type)
171{
ajsb9e70282004-12-08 17:14:45 +0000172 zlog_debug ("%s: %s %p %s %d", func, lookup (mstr, type), memory, file, line);
paul718e3742002-12-13 20:15:29 +0000173}
174
175void *
176mtype_zmalloc (const char *file, int line, int type, size_t size)
177{
178 void *memory;
179
180 mstat[type].c_malloc++;
181 mstat[type].t_malloc++;
182
183 memory = zmalloc (type, size);
184 mtype_log ("zmalloc", memory, file, line, type);
185
186 return memory;
187}
188
189void *
190mtype_zcalloc (const char *file, int line, int type, size_t size)
191{
192 void *memory;
193
194 mstat[type].c_calloc++;
195 mstat[type].t_calloc++;
196
197 memory = zcalloc (type, size);
198 mtype_log ("xcalloc", memory, file, line, type);
199
200 return memory;
201}
202
203void *
204mtype_zrealloc (const char *file, int line, int type, void *ptr, size_t size)
205{
206 void *memory;
207
208 /* Realloc need before allocated pointer. */
209 mstat[type].t_realloc++;
210
211 memory = zrealloc (type, ptr, size);
212
213 mtype_log ("xrealloc", memory, file, line, type);
214
215 return memory;
216}
217
218/* Important function. */
219void
220mtype_zfree (const char *file, int line, int type, void *ptr)
221{
222 mstat[type].t_free++;
223
224 mtype_log ("xfree", ptr, file, line, type);
225
226 zfree (type, ptr);
227}
228
229char *
hassob04c6992004-10-04 19:10:31 +0000230mtype_zstrdup (const char *file, int line, int type, const char *str)
paul718e3742002-12-13 20:15:29 +0000231{
232 char *memory;
233
234 mstat[type].c_strdup++;
235
236 memory = zstrdup (type, str);
237
238 mtype_log ("xstrdup", memory, file, line, type);
239
240 return memory;
241}
242#else
ajsf858e492004-11-16 14:25:30 +0000243static struct
paul718e3742002-12-13 20:15:29 +0000244{
245 char *name;
Chris Caputo228da422009-07-18 05:44:03 +0000246 long alloc;
paul718e3742002-12-13 20:15:29 +0000247} mstat [MTYPE_MAX];
Chris Caputo228da422009-07-18 05:44:03 +0000248#endif /* MEMORY_LOG */
paul718e3742002-12-13 20:15:29 +0000249
250/* Increment allocation counter. */
ajsf858e492004-11-16 14:25:30 +0000251static void
paul718e3742002-12-13 20:15:29 +0000252alloc_inc (int type)
253{
254 mstat[type].alloc++;
255}
256
257/* Decrement allocation counter. */
ajsf858e492004-11-16 14:25:30 +0000258static void
paul718e3742002-12-13 20:15:29 +0000259alloc_dec (int type)
260{
261 mstat[type].alloc--;
262}
David Lamparter6b0655a2014-06-04 06:53:35 +0200263
paul718e3742002-12-13 20:15:29 +0000264/* Looking up memory status from vty interface. */
265#include "vector.h"
266#include "vty.h"
267#include "command.h"
268
ajs7fa25ff2004-11-15 16:12:32 +0000269static void
270log_memstats(int pri)
271{
272 struct mlist *ml;
273
274 for (ml = mlists; ml->list; ml++)
275 {
276 struct memory_list *m;
277
278 zlog (NULL, pri, "Memory utilization in module %s:", ml->name);
279 for (m = ml->list; m->index >= 0; m++)
280 if (m->index && mstat[m->index].alloc)
paul2fd2fd52005-04-15 11:47:15 +0000281 zlog (NULL, pri, " %-30s: %10ld", m->format, mstat[m->index].alloc);
ajs7fa25ff2004-11-15 16:12:32 +0000282 }
283}
284
Chris Caputo228da422009-07-18 05:44:03 +0000285void
286log_memstats_stderr (const char *prefix)
287{
288 struct mlist *ml;
289 struct memory_list *m;
290 int i;
291 int j = 0;
292
293 for (ml = mlists; ml->list; ml++)
294 {
295 i = 0;
296
297 for (m = ml->list; m->index >= 0; m++)
298 if (m->index && mstat[m->index].alloc)
299 {
300 if (!i)
301 fprintf (stderr,
302 "%s: memstats: Current memory utilization in module %s:\n",
303 prefix,
304 ml->name);
305 fprintf (stderr,
306 "%s: memstats: %-30s: %10ld%s\n",
307 prefix,
308 m->format,
309 mstat[m->index].alloc,
310 mstat[m->index].alloc < 0 ? " (REPORT THIS BUG!)" : "");
311 i = j = 1;
312 }
313 }
314
315 if (j)
316 fprintf (stderr,
317 "%s: memstats: NOTE: If configuration exists, utilization may be "
318 "expected.\n",
319 prefix);
320 else
321 fprintf (stderr,
322 "%s: memstats: No remaining tracked memory utilization.\n",
323 prefix);
324}
325
ajsf858e492004-11-16 14:25:30 +0000326static void
ajs24065a32005-10-20 22:28:14 +0000327show_separator(struct vty *vty)
328{
329 vty_out (vty, "-----------------------------\r\n");
330}
331
332static int
paul718e3742002-12-13 20:15:29 +0000333show_memory_vty (struct vty *vty, struct memory_list *list)
334{
335 struct memory_list *m;
ajs24065a32005-10-20 22:28:14 +0000336 int needsep = 0;
paul718e3742002-12-13 20:15:29 +0000337
338 for (m = list; m->index >= 0; m++)
339 if (m->index == 0)
ajs24065a32005-10-20 22:28:14 +0000340 {
341 if (needsep)
342 {
343 show_separator (vty);
344 needsep = 0;
345 }
346 }
347 else if (mstat[m->index].alloc)
348 {
349 vty_out (vty, "%-30s: %10ld\r\n", m->format, mstat[m->index].alloc);
350 needsep = 1;
351 }
352 return needsep;
paul718e3742002-12-13 20:15:29 +0000353}
354
Paul Jakma41be32b2006-03-30 13:53:59 +0000355#ifdef HAVE_MALLINFO
356static int
357show_memory_mallinfo (struct vty *vty)
358{
359 struct mallinfo minfo = mallinfo();
360 char buf[MTYPE_MEMSTR_LEN];
361
362 vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE);
363 vty_out (vty, " Total heap allocated: %s%s",
364 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena),
365 VTY_NEWLINE);
366 vty_out (vty, " Holding block headers: %s%s",
367 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd),
368 VTY_NEWLINE);
369 vty_out (vty, " Used small blocks: %s%s",
370 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks),
371 VTY_NEWLINE);
372 vty_out (vty, " Used ordinary blocks: %s%s",
373 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks),
374 VTY_NEWLINE);
375 vty_out (vty, " Free small blocks: %s%s",
376 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks),
377 VTY_NEWLINE);
378 vty_out (vty, " Free ordinary blocks: %s%s",
379 mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks),
380 VTY_NEWLINE);
381 vty_out (vty, " Ordinary blocks: %ld%s",
382 (unsigned long)minfo.ordblks,
383 VTY_NEWLINE);
384 vty_out (vty, " Small blocks: %ld%s",
385 (unsigned long)minfo.smblks,
386 VTY_NEWLINE);
387 vty_out (vty, " Holding blocks: %ld%s",
388 (unsigned long)minfo.hblks,
389 VTY_NEWLINE);
390 vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s",
391 VTY_NEWLINE);
392 return 1;
393}
394#endif /* HAVE_MALLINFO */
395
paul718e3742002-12-13 20:15:29 +0000396DEFUN (show_memory_all,
397 show_memory_all_cmd,
398 "show memory all",
399 "Show running system information\n"
400 "Memory statistics\n"
401 "All memory statistics\n")
402{
ajs7fa25ff2004-11-15 16:12:32 +0000403 struct mlist *ml;
ajs24065a32005-10-20 22:28:14 +0000404 int needsep = 0;
Paul Jakma41be32b2006-03-30 13:53:59 +0000405
406#ifdef HAVE_MALLINFO
407 needsep = show_memory_mallinfo (vty);
408#endif /* HAVE_MALLINFO */
409
ajs7fa25ff2004-11-15 16:12:32 +0000410 for (ml = mlists; ml->list; ml++)
411 {
ajs24065a32005-10-20 22:28:14 +0000412 if (needsep)
413 show_separator (vty);
414 needsep = show_memory_vty (vty, ml->list);
ajs7fa25ff2004-11-15 16:12:32 +0000415 }
paul718e3742002-12-13 20:15:29 +0000416
417 return CMD_SUCCESS;
418}
419
420ALIAS (show_memory_all,
421 show_memory_cmd,
422 "show memory",
423 "Show running system information\n"
424 "Memory statistics\n")
425
426DEFUN (show_memory_lib,
427 show_memory_lib_cmd,
428 "show memory lib",
429 SHOW_STR
430 "Memory statistics\n"
431 "Library memory\n")
432{
433 show_memory_vty (vty, memory_list_lib);
434 return CMD_SUCCESS;
435}
436
paul2fd2fd52005-04-15 11:47:15 +0000437DEFUN (show_memory_zebra,
438 show_memory_zebra_cmd,
439 "show memory zebra",
440 SHOW_STR
441 "Memory statistics\n"
442 "Zebra memory\n")
443{
444 show_memory_vty (vty, memory_list_zebra);
445 return CMD_SUCCESS;
446}
447
paul718e3742002-12-13 20:15:29 +0000448DEFUN (show_memory_rip,
449 show_memory_rip_cmd,
450 "show memory rip",
451 SHOW_STR
452 "Memory statistics\n"
453 "RIP memory\n")
454{
455 show_memory_vty (vty, memory_list_rip);
456 return CMD_SUCCESS;
457}
458
hassoa94434b2003-05-25 17:10:12 +0000459DEFUN (show_memory_ripng,
460 show_memory_ripng_cmd,
461 "show memory ripng",
462 SHOW_STR
463 "Memory statistics\n"
464 "RIPng memory\n")
465{
466 show_memory_vty (vty, memory_list_ripng);
467 return CMD_SUCCESS;
468}
469
Paul Jakma57345092011-12-25 17:52:09 +0100470DEFUN (show_memory_babel,
471 show_memory_babel_cmd,
472 "show memory babel",
473 SHOW_STR
474 "Memory statistics\n"
475 "Babel memory\n")
476{
477 show_memory_vty (vty, memory_list_babel);
478 return CMD_SUCCESS;
479}
480
paul718e3742002-12-13 20:15:29 +0000481DEFUN (show_memory_bgp,
482 show_memory_bgp_cmd,
483 "show memory bgp",
484 SHOW_STR
485 "Memory statistics\n"
486 "BGP memory\n")
487{
488 show_memory_vty (vty, memory_list_bgp);
489 return CMD_SUCCESS;
490}
491
492DEFUN (show_memory_ospf,
493 show_memory_ospf_cmd,
494 "show memory ospf",
495 SHOW_STR
496 "Memory statistics\n"
497 "OSPF memory\n")
498{
499 show_memory_vty (vty, memory_list_ospf);
500 return CMD_SUCCESS;
501}
502
503DEFUN (show_memory_ospf6,
504 show_memory_ospf6_cmd,
505 "show memory ospf6",
506 SHOW_STR
507 "Memory statistics\n"
508 "OSPF6 memory\n")
509{
510 show_memory_vty (vty, memory_list_ospf6);
511 return CMD_SUCCESS;
512}
513
jardin9e867fe2003-12-23 08:56:18 +0000514DEFUN (show_memory_isis,
515 show_memory_isis_cmd,
516 "show memory isis",
517 SHOW_STR
518 "Memory statistics\n"
519 "ISIS memory\n")
520{
521 show_memory_vty (vty, memory_list_isis);
522 return CMD_SUCCESS;
523}
524
Everton Marques871dbcf2009-08-11 15:43:05 -0300525DEFUN (show_memory_pim,
526 show_memory_pim_cmd,
527 "show memory pim",
528 SHOW_STR
529 "Memory statistics\n"
530 "PIM memory\n")
531{
532 show_memory_vty (vty, memory_list_pim);
533 return CMD_SUCCESS;
534}
535
paul718e3742002-12-13 20:15:29 +0000536void
ajsf858e492004-11-16 14:25:30 +0000537memory_init (void)
paul718e3742002-12-13 20:15:29 +0000538{
Paul Jakma62687ff2008-08-23 14:27:06 +0100539 install_element (RESTRICTED_NODE, &show_memory_cmd);
540 install_element (RESTRICTED_NODE, &show_memory_all_cmd);
541 install_element (RESTRICTED_NODE, &show_memory_lib_cmd);
542 install_element (RESTRICTED_NODE, &show_memory_rip_cmd);
543 install_element (RESTRICTED_NODE, &show_memory_ripng_cmd);
Matthieu Boutier2236df02012-01-19 22:37:38 +0100544 install_element (RESTRICTED_NODE, &show_memory_babel_cmd);
Paul Jakma62687ff2008-08-23 14:27:06 +0100545 install_element (RESTRICTED_NODE, &show_memory_bgp_cmd);
546 install_element (RESTRICTED_NODE, &show_memory_ospf_cmd);
547 install_element (RESTRICTED_NODE, &show_memory_ospf6_cmd);
548 install_element (RESTRICTED_NODE, &show_memory_isis_cmd);
549
paul718e3742002-12-13 20:15:29 +0000550 install_element (VIEW_NODE, &show_memory_cmd);
551 install_element (VIEW_NODE, &show_memory_all_cmd);
552 install_element (VIEW_NODE, &show_memory_lib_cmd);
553 install_element (VIEW_NODE, &show_memory_rip_cmd);
hassoa94434b2003-05-25 17:10:12 +0000554 install_element (VIEW_NODE, &show_memory_ripng_cmd);
Matthieu Boutier2236df02012-01-19 22:37:38 +0100555 install_element (VIEW_NODE, &show_memory_babel_cmd);
paul718e3742002-12-13 20:15:29 +0000556 install_element (VIEW_NODE, &show_memory_bgp_cmd);
557 install_element (VIEW_NODE, &show_memory_ospf_cmd);
558 install_element (VIEW_NODE, &show_memory_ospf6_cmd);
jardin9e867fe2003-12-23 08:56:18 +0000559 install_element (VIEW_NODE, &show_memory_isis_cmd);
Everton Marques871dbcf2009-08-11 15:43:05 -0300560 install_element (VIEW_NODE, &show_memory_pim_cmd);
paul718e3742002-12-13 20:15:29 +0000561
562 install_element (ENABLE_NODE, &show_memory_cmd);
563 install_element (ENABLE_NODE, &show_memory_all_cmd);
564 install_element (ENABLE_NODE, &show_memory_lib_cmd);
paul2fd2fd52005-04-15 11:47:15 +0000565 install_element (ENABLE_NODE, &show_memory_zebra_cmd);
paul718e3742002-12-13 20:15:29 +0000566 install_element (ENABLE_NODE, &show_memory_rip_cmd);
hassoa94434b2003-05-25 17:10:12 +0000567 install_element (ENABLE_NODE, &show_memory_ripng_cmd);
Matthieu Boutier2236df02012-01-19 22:37:38 +0100568 install_element (ENABLE_NODE, &show_memory_babel_cmd);
paul718e3742002-12-13 20:15:29 +0000569 install_element (ENABLE_NODE, &show_memory_bgp_cmd);
570 install_element (ENABLE_NODE, &show_memory_ospf_cmd);
571 install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
Everton Marques871dbcf2009-08-11 15:43:05 -0300572 install_element (ENABLE_NODE, &show_memory_pim_cmd);
paul718e3742002-12-13 20:15:29 +0000573}
David Lamparter6b0655a2014-06-04 06:53:35 +0200574
Paul Jakma41be32b2006-03-30 13:53:59 +0000575/* Stats querying from users */
576/* Return a pointer to a human friendly string describing
577 * the byte count passed in. E.g:
578 * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
579 * Up to 4 significant figures will be given.
580 * The pointer returned may be NULL (indicating an error)
581 * or point to the given buffer, or point to static storage.
582 */
583const char *
584mtype_memstr (char *buf, size_t len, unsigned long bytes)
585{
586 unsigned int t, g, m, k;
587
588 /* easy cases */
589 if (!bytes)
590 return "0 bytes";
591 if (bytes == 1)
592 return "1 byte";
593
594 if (sizeof (unsigned long) >= 8)
595 /* Hacked to make it not warn on ILP32 machines
596 * Shift will always be 40 at runtime. See below too */
597 t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0);
598 else
599 t = 0;
600 g = bytes >> 30;
601 m = bytes >> 20;
602 k = bytes >> 10;
603
604 if (t > 10)
605 {
606 /* The shift will always be 39 at runtime.
607 * Just hacked to make it not warn on 'smaller' machines.
608 * Static compiler analysis should mean no extra code
609 */
Paul Jakma912df1e2008-01-08 13:50:11 +0000610 if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0)))
Paul Jakma41be32b2006-03-30 13:53:59 +0000611 t++;
612 snprintf (buf, len, "%4d TiB", t);
613 }
614 else if (g > 10)
615 {
616 if (bytes & (1 << 29))
617 g++;
618 snprintf (buf, len, "%d GiB", g);
619 }
620 else if (m > 10)
621 {
622 if (bytes & (1 << 19))
623 m++;
624 snprintf (buf, len, "%d MiB", m);
625 }
626 else if (k > 10)
627 {
628 if (bytes & (1 << 9))
629 k++;
630 snprintf (buf, len, "%d KiB", k);
631 }
632 else
633 snprintf (buf, len, "%ld bytes", bytes);
634
635 return buf;
636}
637
638unsigned long
639mtype_stats_alloc (int type)
640{
641 return mstat[type].alloc;
642}