Skip to content

Commit

Permalink
synchronize deferred list size before free span (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjansson committed May 30, 2022
1 parent eede53d commit 8b64cb6
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion rpmalloc/rpmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,16 @@ _rpmalloc_deallocate_direct_small_or_medium(span_t* span, void* block) {
--span->used_count;
span->free_list = block;
if (UNEXPECTED(span->used_count == span->list_size)) {
// If there are no used blocks it is guaranteed that no other external thread is accessing the span
if (span->used_count) {
// Make sure we have synchronized the deferred list and list size by using acquire semantics
// and guarantee that no external thread is accessing span concurrently
void* free_list;
do {
free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER);
} while (free_list == INVALID_POINTER);
atomic_store_ptr_release(&span->free_list_deferred, free_list);
}
_rpmalloc_span_double_link_list_remove(&heap->size_class[span->size_class].partial_span, span);
_rpmalloc_span_release_to_cache(heap, span);
}
Expand Down Expand Up @@ -2408,8 +2418,9 @@ _rpmalloc_deallocate_defer_small_or_medium(span_t* span, void* block) {
} while (free_list == INVALID_POINTER);
*((void**)block) = free_list;
uint32_t free_count = ++span->list_size;
int all_deferred_free = (free_count == span->block_count);
atomic_store_ptr_release(&span->free_list_deferred, block);
if (free_count == span->block_count) {
if (all_deferred_free) {
// Span was completely freed by this block. Due to the INVALID_POINTER spin lock
// no other thread can reach this state simultaneously on this span.
// Safe to move to owner heap deferred cache
Expand Down

0 comments on commit 8b64cb6

Please sign in to comment.