big allocs in kernel heap
"François Revol" <[email protected]> Thu, 06 Sep 2007 21:00:07 +0200
| Newsgroups | gmane.os.openbeos.kernel.devel |
|---|---|
| Message-ID | <1208851988-BeMail@laptop> |
Hi, I got annoyed by those big unfreeable allocations (that also paniced in realloc (I know, according to Travis realloc() shouldn't even be in the kernel)), so I made a little workaround. It's likely slow as hell but should work at least. Comments ? Is a replacement planned for some year in the future ? :) François. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Open-beos-kernel-devel mailing list Open-beos-kernel-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/open-beos-kernel-devel
kernheap.bigrealloc.diff
(text/plain, 3.2 KB)
Index: src/system/kernel/heap.c
===================================================================
--- src/system/kernel/heap.c (revision 22190)
+++ src/system/kernel/heap.c (working copy)
@@ -72,6 +72,14 @@
uint16 cleaning : 1;
uint16 in_use : 1;
} PACKED;
+// used for bin==bin_count allocations
+#define allocation_id free_count
+static vint32 current_alloc_id = 0;
+inline int32 next_alloc_id(void);
+inline int32 next_alloc_id(void)
+{
+ return atomic_add(¤t_alloc_id, 1) & ((1<<(9-1))-1);
+}
static struct heap_page *heap_alloc_table;
static addr_t heap_base_ptr;
@@ -451,9 +459,37 @@
break;
if (bin_index == bin_count) {
- address = raw_alloc(size, bin_index);
- dprintf("heap: allocated big chunk (%ld bytes), it will never be freed!\n",
- size);
+ int32 alloc_id;
+ alloc_id = next_alloc_id();
+
+ // try to find freed blocks first...
+ if (size < (heap_base_ptr - heap_base) / 10) { // but don't try too hard
+ int first = -1;
+ page = heap_alloc_table;
+ for (i = 0; i < (heap_base_ptr-heap_base)/B_PAGE_SIZE; i++) {
+ if (page[i].in_use) {
+ first = -1;
+ continue;
+ }
+ if (first > 0) {
+ if ((1 + i - first)*B_PAGE_SIZE > size)
+ break;
+ }
+ first = i;
+ }
+ if (first > -1)
+ address = (void *)(heap_base + first * B_PAGE_SIZE);
+
+ }
+ if (address == NULL)
+ address = raw_alloc(size, bin_index);
+ page = &heap_alloc_table[((unsigned int)address - heap_base) / B_PAGE_SIZE];
+ for (i = 0; i < (size+B_PAGE_SIZE-1)/B_PAGE_SIZE; i++) {
+ page[i].in_use = 1;
+ page[i].cleaning = 0;
+ page[i].bin_index = bin_count;
+ page[i].allocation_id = alloc_id;
+ }
} else {
if (bins[bin_index].free_list != NULL) {
address = bins[bin_index].free_list;
@@ -600,6 +636,21 @@
// TODO: since the heap must be replaced anyway, we don't
// free this allocation anymore... (tracking them would
// require some extra stuff)
+
+ for (i = 1; i <= (heap_base_ptr-heap_base)/B_PAGE_SIZE; i++) {
+ if (!page[i].in_use)
+ break;
+ if (page[i].bin_index != bin_count)
+ break;
+ if (page[i].allocation_id != page[0].allocation_id)
+ break;
+ page[i].in_use = 0;
+ page[i].cleaning = 0;
+ page[i].allocation_id = 0;
+ }
+ page[0].in_use = 0;
+ page[0].cleaning = 0;
+ page[0].allocation_id = 0;
}
mutex_unlock(&heap_lock);
@@ -644,11 +695,25 @@
TRACE(("realloc(): page %p: bin_index %d, free_count %d\n", page, page->bin_index, page->free_count));
- if (page[0].bin_index >= bin_count)
+ if (page[0].bin_index > bin_count)
panic("realloc(): page %p: invalid bin_index %d\n", page, page->bin_index);
- maxSize = bins[page[0].bin_index].element_size;
- minSize = page[0].bin_index > 0 ? bins[page[0].bin_index - 1].element_size : 0;
+ if (page[0].bin_index < bin_count) {
+ maxSize = bins[page[0].bin_index].element_size;
+ minSize = page[0].bin_index > 0 ? bins[page[0].bin_index - 1].element_size : 0;
+ } else {
+ int i;
+ for (i = 1; (addr_t)&page[i] < heap_base; i++) {
+ if (!page[i].in_use)
+ break;
+ if (page[i].bin_index != bin_count)
+ break;
+ if (page[i].allocation_id != page[0].allocation_id)
+ break;
+ }
+ minSize = 0;
+ maxSize = i * B_PAGE_SIZE;
+ }
mutex_unlock(&heap_lock);