diff --git a/src/mem/corealloc.h b/src/mem/corealloc.h index 7ec0a31..0105df0 100644 --- a/src/mem/corealloc.h +++ b/src/mem/corealloc.h @@ -330,12 +330,31 @@ namespace snmalloc return chunk_record; } + template SNMALLOC_SLOW_PATH void dealloc_local_slabs(sizeclass_t sizeclass) { // Return unused slabs of sizeclass_t back to global allocator alloc_classes[sizeclass].queue.filter([this, sizeclass](Metaslab* meta) { + auto domesticate = + [this](freelist::QueuePtr p) SNMALLOC_FAST_PATH_LAMBDA { + auto res = + capptr_domesticate(backend_state_ptr(), p); +#ifdef SNMALLOC_TRACING + if (res.unsafe_ptr() != p.unsafe_ptr()) + printf( + "Domesticated %p to %p!\n", p.unsafe_ptr(), res.unsafe_ptr()); +#endif + return res; + }; + if (meta->needed() != 0) + { + if (check_slabs) + { + meta->free_queue.validate(entropy.get_free_list_key(), domesticate); + } return false; + } alloc_classes[sizeclass].length--; alloc_classes[sizeclass].unused--; @@ -789,7 +808,7 @@ namespace snmalloc // We may now have unused slabs, return to the global allocator. for (sizeclass_t sizeclass = 0; sizeclass < NUM_SIZECLASSES; sizeclass++) { - dealloc_local_slabs(sizeclass); + dealloc_local_slabs(sizeclass); } return posted; diff --git a/src/mem/freelist.h b/src/mem/freelist.h index b58978a..7b6e3ca 100644 --- a/src/mem/freelist.h +++ b/src/mem/freelist.h @@ -116,6 +116,13 @@ namespace snmalloc template class T { + template< + bool, + bool, + SNMALLOC_CONCEPT(capptr::ConceptBound), + SNMALLOC_CONCEPT(capptr::ConceptBound)> + friend class Builder; + friend class Object; union @@ -699,6 +706,40 @@ namespace snmalloc init(); return {first, last}; } + + template + SNMALLOC_FAST_PATH void + validate(const FreeListKey& key, Domesticator domesticate) + { +#ifdef SNMALLOC_CHECK_CLIENT + for (uint32_t i = 0; i < LENGTH; i++) + { + if (&head[i] == end[i]) + { + SNMALLOC_ASSERT(length[i] == 0); + continue; + } + + size_t count = 1; + auto curr = read_head(i, key); + auto prev = get_fake_signed_prev(i, key); + while (true) + { + curr->check_prev(prev); + if (address_cast(&(curr->next_object)) == address_cast(end[i])) + break; + count++; + auto next = curr->read_next(key, domesticate); + prev = signed_prev(address_cast(curr), address_cast(next), key); + curr = next; + } + SNMALLOC_ASSERT(count == length[i]); + } +#else + UNUSED(key); + UNUSED(domesticate); +#endif + } }; } // namespace freelist } // namespace snmalloc