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:
parent
45eb999ec8
commit
c1de3c34b3
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user