aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-18 21:51:06 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-18 21:51:06 +0000
commit6f9d2dab5ff8d60ed805a821e9c7d2272c753e81 (patch)
treed1e4b06be64500b9f6c2c75f360778a3fcf564c4
parent579d4257024dc37f41439f268cc6bb815ada84db (diff)
downloadlpsm-6f9d2dab5ff8d60ed805a821e9c7d2272c753e81.tar.gz
lpsm-6f9d2dab5ff8d60ed805a821e9c7d2272c753e81.tar.xz
lpsm-6f9d2dab5ff8d60ed805a821e9c7d2272c753e81.zip
Add objstore_arena_stats()objstore-0.0.1
Add additional debugging output
-rw-r--r--alloc.c99
-rw-r--r--arena.c19
-rw-r--r--lpsm.h9
3 files changed, 113 insertions, 14 deletions
diff --git a/alloc.c b/alloc.c
index c39092a..0fceeac 100644
--- a/alloc.c
+++ b/alloc.c
@@ -50,6 +50,8 @@ struct slab_info {
int size; /* Size of SLAB */
int count; /* SLABs per page */
int data_offset; /* Start of data area */
+ int total_pages; /* Count of pages allocaed to this size SLAB */
+ int alloc_slabs; /* Count of SLABs currently in use */
struct slab_header *list;
};
@@ -235,11 +237,14 @@ static struct arena_header *ah;
/*
* Debugging routine to print the number of allocations of each size
*/
-void buddy_count(void)
+void print_statistics(void)
{
int i, o, obit, ebit, xbit;
- int fcount, acount;
+ 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 ;
@@ -263,13 +268,90 @@ void buddy_count(void)
bf += fcount * (1UL << o);
ba += acount * (1UL << o);
}
- DPRINTF((" bytes: %lu free, %lu allocated, %lu total\n",
+ 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));
}
#else
-#define buddy_count() ((void)0)
+#define print_statistics() ((void)0)
#endif
-
+
+/*
+ * Get allocation statistics. This returned a malloc()'d list of
+ * {block size, free blocks, allocated blocks} followed by an
+ * all-zero datum.
+ */
+struct objstore_arena_stats *objstore_arena_stats(void)
+{
+ struct objstore_arena_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 objstore_arena_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;
+}
+
/*
* Initalize the object store arena allocator. This returns NULL
* on failure, or a pointer to the "root data pointer" array if
@@ -504,7 +586,7 @@ static void *objstore_malloc_buddy(size_t size)
xbit = objstore_find_free_chunk(rorder);
if ( !xbit ) {
/* Need to extend */
- buddy_count(); /* DEBUG */
+ print_statistics(); /* DEBUG */
if ( objstore_extend_arena(ah->arena_size_lg2 + 1) )
return NULL; /* Failed to extend */
}
@@ -551,6 +633,8 @@ static struct slab_header *objstore_make_new_slab(struct slab_info *si, int inde
assert(sh->next->index == index);
}
+ si->total_pages++;
+
return (si->list = sh);
}
@@ -597,6 +681,7 @@ static void *objstore_malloc_slab(size_t size)
assert(which >= 0); /* Otherwise something is bad... */
clr_bit(slab_bitmap, which); /* No longer available */
+ si->alloc_slabs++;
if ( --(sh->free_count) == 0 ) {
/* We just allocated the last slab, take off the free list */
@@ -708,6 +793,7 @@ static void objstore_free_slab(void *ptr)
assert(offset == which*si->size);
free_count = sh->free_count;
+ si->alloc_slabs--;
if ( free_count == si->count-1 ) {
/* Deallocated the entire page; give back to buddy system */
@@ -717,6 +803,7 @@ static void objstore_free_slab(void *ptr)
sh->next->rev = sh->rev;
assert(sh->next->index == sh->index);
}
+ si->total_pages--;
#ifndef NDEBUG
/* This unfortunately makes the page dirty */
memset(sh, 0, BUDDY_SIZE_MIN);
diff --git a/arena.c b/arena.c
index 4d3f611..3ebd885 100644
--- a/arena.c
+++ b/arena.c
@@ -115,13 +115,14 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
struct sigcontext *ctxt;
# ifdef __i386__ /* This is so specific to Linux/i386 */
+ /* Don't even begin to ask me where the 0x14 comes from */
+ ctxt = (struct sigcontext *)((char *)ptr + 0x14);
+
if ( siginfo->si_code == 0 ) {
/* Old kernel. Fill in data to the best of our knowledge. */
- /* Don't even begin to ask me where the 0x14 comes from */
- ctxt = (struct sigcontext *)((char *)ptr + 0x14);
- if ( ctxt->trapno == 14 ) {
- /* Linux/i386 uses unmapped pages to mimic PROT_NONE, so we can't
- tell ACCERR and MAPERR apart from the register state */
+ if ( ctxt->trapno == 14 ) {
+ /* Linux/i386 uses unmapped pages to mimic PROT_NONE, so we can't
+ tell ACCERR and MAPERR apart from the register state */
siginfo->si_code = SEGV_ACCERR;
siginfo->si_addr = (void *)ctxt->cr2;
}
@@ -142,6 +143,14 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
sigemptyset(&dfl.sa_mask);
dfl.sa_flags = SA_ONESHOT;
sigaction(SIGSEGV, &dfl, NULL);
+
+#ifdef __linux
+#ifdef __i386__
+ /* Technically unsafe, but who cares at this point... */
+ fprintf(stderr, "SIGSEGV at %p, %%eip = %p\n",
+ siginfo->si_addr, (void *)ctxt->eip);
+#endif
+#endif
errno = old_errno;
return; /* Re-take fault */
diff --git a/lpsm.h b/lpsm.h
index d0763e5..4b96795 100644
--- a/lpsm.h
+++ b/lpsm.h
@@ -51,7 +51,10 @@ void **objstore_arena_init(const char *, const char *);
void *objstore_malloc(size_t);
void objstore_free(void *);
void *objstore_realloc(void *, size_t);
-
-void **objstore_get_root_ptrs(void);
-
+struct objstore_arena_stats {
+ size_t size;
+ size_t free;
+ size_t alloc;
+};
+struct objstore_arena_stats *objstore_arena_stats(void);
#endif