Added deferred_free() function, that can be used to free allocations

in code that has interrupts disabled. The chunks of memories are queued
and free()d periodically by a kernel daemon.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24332 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-03-09 17:44:55 +00:00
parent 45eb999ec8
commit c1de3c34b3
2 changed files with 48 additions and 0 deletions

View File

@ -24,6 +24,8 @@ extern "C" {
void *memalign(size_t alignment, size_t size);
void deferred_free(void* block);
status_t heap_init(addr_t heapBase, size_t heapSize);
status_t heap_init_post_sem();
status_t heap_init_post_thread();

View File

@ -19,6 +19,8 @@
#include <team.h>
#include <thread.h>
#include <tracing.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
#include <vm.h>
//#define TRACE_HEAP
@ -81,6 +83,10 @@ typedef struct heap_allocator_s {
heap_allocator_s * next;
} heap_allocator;
struct DeferredFreeListEntry : DoublyLinkedListLinkImpl<DeferredFreeListEntry> {
};
typedef DoublyLinkedList<DeferredFreeListEntry> DeferredFreeList;
static heap_allocator *sHeapList = NULL;
static heap_allocator *sLastGrowRequest = NULL;
static heap_allocator *sGrowHeap = NULL;
@ -88,6 +94,10 @@ static thread_id sHeapGrowThread = -1;
static sem_id sHeapGrowSem = -1;
static sem_id sHeapGrownNotify = -1;
static DeferredFreeList sDeferredFreeList;
static spinlock sDeferredFreeListLock;
// #pragma mark - Tracing
@ -962,6 +972,25 @@ heap_realloc(heap_allocator *heap, void *address, void **newAddress,
}
static void
deferred_deleter(void *arg, int iteration)
{
// move entries to on-stack list
InterruptsSpinLocker locker(sDeferredFreeListLock);
if (sDeferredFreeList.IsEmpty())
return;
DeferredFreeList entries;
entries.MoveFrom(&sDeferredFreeList);
locker.Unlock();
// free the entries
while (DeferredFreeListEntry* entry = entries.RemoveHead())
free(entry);
}
// #pragma mark -
@ -1092,6 +1121,9 @@ heap_init_post_thread()
return sHeapGrowThread;
}
if (register_kernel_daemon(deferred_deleter, NULL, 50) != B_OK)
panic("heap_init_post_thread(): failed to init deferred deleter");
send_signal_etc(sHeapGrowThread, SIGCONT, B_DO_NOT_RESCHEDULE);
return B_OK;
}
@ -1236,3 +1268,17 @@ calloc(size_t numElements, size_t size)
return address;
}
void
deferred_free(void* block)
{
if (block == NULL)
return;
// TODO: Use SinglyLinkedList, so that we only need sizeof(void*).
DeferredFreeListEntry* entry = new(block) DeferredFreeListEntry;
InterruptsSpinLocker _(sDeferredFreeListLock);
sDeferredFreeList.Add(entry);
}