aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-20 02:34:02 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-20 02:34:02 +0000
commitc315f1e4bb97c797fb7b3e22e40e23384d17008d (patch)
tree9d00e14e6757e8172071acf2cf5ac805602dc4c5
parentbe9d8ab8ec452c46777b2eb4ae925843d7361c7b (diff)
downloadlpsm-c315f1e4bb97c797fb7b3e22e40e23384d17008d.tar.gz
lpsm-c315f1e4bb97c797fb7b3e22e40e23384d17008d.tar.xz
lpsm-c315f1e4bb97c797fb7b3e22e40e23384d17008d.zip
Add missing file (statistics generation.)lpsm-0.1.2
-rw-r--r--stats.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/stats.c b/stats.c
new file mode 100644
index 0000000..1380d92
--- /dev/null
+++ b/stats.c
@@ -0,0 +1,146 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, Inc.,
+ * 59 Temple Place Ste 330, Boston MA 02111-1307, USA, version 2.1,
+ * incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * stats.c
+ *
+ * Produce memory allocation statistics.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+
+#include "lpsm.h"
+#include "internals.h"
+#include "bitops.h"
+
+#ifdef PRINT_DEBUG_INFO
+/*
+ * Debugging routine to print the number of allocations of each size
+ */
+void lpsm_print_statistics(void)
+{
+ int i, o, obit, ebit, xbit;
+ int fcount, acount, total_slabs;
+ unsigned long bt = 0, bf = 0, ba = 0;
+ struct slab_info *si;
+
+ /* Print buddy system stats */
+
+ for ( i = 0, o = AH->arena_size_lg2 ;
+ o >= BUDDY_ORDER_MIN ;
+ i++, o-- ) {
+ obit = 1 << i;
+ ebit = obit << 1;
+ fcount = acount = 0;
+ for ( xbit = obit ; xbit < ebit ; xbit++ ) {
+ if ( test_bit(AH->free_bitmap, xbit) )
+ fcount++;
+ }
+ for ( xbit = obit ; xbit < ebit ; xbit++ ) {
+ if ( test_bit(AH->alloc_bitmap, xbit) )
+ acount++;
+ }
+
+ DPRINTF((" rorder %2d order %2d free %8d used %8d\n",
+ i, AH->arena_size_lg2-i, fcount, acount));
+
+ bt += (fcount+acount) * (1UL << o);
+ bf += fcount * (1UL << o);
+ ba += acount * (1UL << o);
+ }
+ DPRINTF((" buddy: %lu bytes free, %lu bytes allocated, %lu total\n",
+ bf, ba, bt));
+
+ bt = bf = ba = 0;
+
+ for ( si = &AH->slab[0], i = 0 ;
+ i < SLAB_INFO_COUNT ;
+ i++, si++ ) {
+ if ( !si->size )
+ break;
+ total_slabs = si->total_pages * si->count;
+ DPRINTF((" slab size %4d free %8d used %8d\n",
+ si->size, total_slabs-si->alloc_slabs, si->alloc_slabs));
+ bt += total_slabs * si->size;
+ bf += (total_slabs-si->alloc_slabs) * si->size;
+ ba += si->alloc_slabs * si->size;
+ }
+ DPRINTF((" slab: %lu bytes free, %lu bytes allocated, %lu total\n",
+ bf, ba, bt));
+}
+#endif
+
+/*
+ * Get allocation statistics. This returned a malloc()'d list of
+ * {block size, free blocks, allocated blocks} followed by an
+ * all-zero datum.
+ */
+struct lpsm_alloc_stats *lpsm_alloc_stats(void)
+{
+ struct lpsm_alloc_stats *as, *asp;
+ struct slab_info *si;
+ int nb, ns;
+ int i, o;
+ int xbit, obit, ebit;
+ size_t fcount, acount, *last_buddy_alloc;
+
+ /* Compute number of buddy and slab allocation types */
+ nb = AH->arena_size_lg2-BUDDY_ORDER_MIN+1;
+ for ( ns = 0 ; ns < SLAB_INFO_COUNT ; ns++ )
+ if ( !AH->slab[ns].size )
+ break;
+
+ as = malloc((nb+ns+1) * sizeof(struct lpsm_alloc_stats));
+ if ( !as )
+ return NULL;
+
+ for ( asp = as, i = 0, o = AH->arena_size_lg2 ;
+ o >= BUDDY_ORDER_MIN ;
+ asp++, i++, o-- ) {
+ asp->size = (size_t)1 << o;
+ obit = 1 << i;
+ ebit = obit << 1;
+ fcount = acount = 0;
+ for ( xbit = obit ; xbit < ebit ; xbit++ ) {
+ if ( test_bit(AH->free_bitmap, xbit) )
+ fcount++;
+ }
+ asp->free = fcount;
+ for ( xbit = obit ; xbit < ebit ; xbit++ ) {
+ if ( test_bit(AH->alloc_bitmap, xbit) )
+ acount++;
+ }
+ asp->alloc = acount;
+ }
+
+ /* The alloc counter for the last buddy size include all the slab blocks.
+ We want to count them separately. */
+ last_buddy_alloc = &asp[-1].alloc;
+
+ for ( i = 0, si = &AH->slab[0] ;
+ i < SLAB_INFO_COUNT && si->size ;
+ i++, si++, asp++ ) {
+ last_buddy_alloc -= si->total_pages;
+ asp->size = si->size;
+ asp->alloc = si->alloc_slabs;
+ asp->free = (si->total_pages * si->count) - si->alloc_slabs;
+ }
+ /* Sentinel block at end */
+ asp->size = asp->alloc = asp->free = 0;
+ return as;
+}
+