diff --git a/headers/private/kernel/heap.h b/headers/private/kernel/heap.h index c0b7980365..6125789fdc 100644 --- a/headers/private/kernel/heap.h +++ b/headers/private/kernel/heap.h @@ -75,6 +75,9 @@ status_t heap_init_post_thread(); #include +#include + + static const struct nogrow_t { } nogrow = {}; @@ -84,6 +87,16 @@ operator new(size_t size, const nogrow_t& nogrow) throw() return malloc_nogrow(size); } + +class DeferredDeletable : public SinglyLinkedListLinkImpl { +public: + virtual ~DeferredDeletable(); +}; + + +void deferred_delete(DeferredDeletable* deletable); + + #endif /* __cplusplus */ diff --git a/src/system/kernel/heap.cpp b/src/system/kernel/heap.cpp index b927735e23..34151c9eb3 100644 --- a/src/system/kernel/heap.cpp +++ b/src/system/kernel/heap.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include @@ -124,9 +123,11 @@ typedef struct area_allocation_info_s { void * allocation_base; } area_allocation_info; -struct DeferredFreeListEntry : DoublyLinkedListLinkImpl { +struct DeferredFreeListEntry : SinglyLinkedListLinkImpl { }; -typedef DoublyLinkedList DeferredFreeList; + +typedef SinglyLinkedList DeferredFreeList; +typedef SinglyLinkedList DeferredDeletableList; // Heap class configuration #define HEAP_CLASS_COUNT 3 @@ -173,6 +174,7 @@ static sem_id sHeapGrownNotify = -1; static bool sAddGrowHeap = false; static DeferredFreeList sDeferredFreeList; +static DeferredDeletableList sDeferredDeletableList; static spinlock sDeferredFreeListLock; @@ -1610,7 +1612,7 @@ heap_class_for(size_t size) static void deferred_deleter(void *arg, int iteration) { - // move entries to on-stack list + // move entries and deletables to on-stack lists InterruptsSpinLocker locker(sDeferredFreeListLock); if (sDeferredFreeList.IsEmpty()) return; @@ -1618,11 +1620,18 @@ deferred_deleter(void *arg, int iteration) DeferredFreeList entries; entries.MoveFrom(&sDeferredFreeList); + DeferredDeletableList deletables; + deletables.MoveFrom(&sDeferredDeletableList); + locker.Unlock(); // free the entries while (DeferredFreeListEntry* entry = entries.RemoveHead()) free(entry); + + // delete the deletables + while (DeferredDeletable* deletable = deletables.RemoveHead()) + delete deletable; } @@ -2035,7 +2044,6 @@ 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); @@ -2078,3 +2086,19 @@ malloc_referenced_release(void* data) if (atomic_add(referencedData, -1) < 1) free(referencedData); } + + +DeferredDeletable::~DeferredDeletable() +{ +} + + +void +deferred_delete(DeferredDeletable* deletable) +{ + if (deletable == NULL) + return; + + InterruptsSpinLocker _(sDeferredFreeListLock); + sDeferredDeletableList.Add(deletable); +}