wingo pushed a commit to branch wip-whippet in repository guile. commit 3955d2ad96017c45baf0f056811c84cc17627e64 Author: Andy Wingo <wi...@igalia.com> AuthorDate: Mon Sep 30 20:52:45 2024 +0200
Factor out locking utils to separate header --- src/copy-space.h | 74 ++++++++++++------------------ src/gc-lock.h | 24 ++++++++++ src/nofl-space.h | 134 ++++++++++++++++++++++++++++++------------------------- 3 files changed, 126 insertions(+), 106 deletions(-) diff --git a/src/copy-space.h b/src/copy-space.h index b66efad97..d09609dfe 100644 --- a/src/copy-space.h +++ b/src/copy-space.h @@ -17,6 +17,7 @@ #include "gc-align.h" #include "gc-attrs.h" #include "gc-inline.h" +#include "gc-lock.h" #include "spin.h" // A copy space: a block-structured space that traces via evacuation. @@ -114,10 +115,6 @@ struct copy_space_block_stack { struct copy_space_block_list list; }; -struct copy_space_lock { - pthread_mutex_t *lock; -}; - struct copy_space { pthread_mutex_t lock; struct copy_space_block_stack empty; @@ -145,22 +142,9 @@ struct copy_space_allocator { struct copy_space_block *block; }; -static struct copy_space_lock -copy_space_lock_acquire(pthread_mutex_t *lock) { - pthread_mutex_lock(lock); - return (struct copy_space_lock){ lock }; -} - -static void -copy_space_lock_release(struct copy_space_lock *lock) { - GC_ASSERT(lock->lock); - pthread_mutex_unlock(lock->lock); - lock->lock = NULL; -} - -static struct copy_space_lock +static struct gc_lock copy_space_lock(struct copy_space *space) { - return copy_space_lock_acquire(&space->lock); + return gc_lock_acquire(&space->lock); } static void @@ -189,7 +173,7 @@ copy_space_block_list_pop(struct copy_space_block_list *list) { static void copy_space_block_stack_push(struct copy_space_block_stack *stack, struct copy_space_block *block, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { struct copy_space_block *next = stack->list.head; block->next = next; stack->list.head = block; @@ -197,7 +181,7 @@ copy_space_block_stack_push(struct copy_space_block_stack *stack, static struct copy_space_block* copy_space_block_stack_pop(struct copy_space_block_stack *stack, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { struct copy_space_block *head = stack->list.head; if (head) { stack->list.head = head->next; @@ -208,7 +192,7 @@ copy_space_block_stack_pop(struct copy_space_block_stack *stack, static struct copy_space_block* copy_space_pop_empty_block(struct copy_space *space, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { struct copy_space_block *ret = copy_space_block_stack_pop(&space->empty, lock); if (ret) @@ -219,7 +203,7 @@ copy_space_pop_empty_block(struct copy_space *space, static void copy_space_push_empty_block(struct copy_space *space, struct copy_space_block *block, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { copy_space_block_stack_push(&space->empty, block, lock); } @@ -236,21 +220,21 @@ copy_space_push_full_block(struct copy_space *space, static struct copy_space_block* copy_space_pop_partly_full_block(struct copy_space *space, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { return copy_space_block_stack_pop(&space->partly_full, lock); } static void copy_space_push_partly_full_block(struct copy_space *space, struct copy_space_block *block, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { copy_space_block_stack_push(&space->partly_full, block, lock); } static void copy_space_page_out_block(struct copy_space *space, struct copy_space_block *block, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { copy_space_block_stack_push (block->in_core ? &space->paged_out[0] @@ -261,7 +245,7 @@ copy_space_page_out_block(struct copy_space *space, static struct copy_space_block* copy_space_page_in_block(struct copy_space *space, - const struct copy_space_lock *lock) { + const struct gc_lock *lock) { for (int age = 0; age < COPY_SPACE_PAGE_OUT_QUEUE_SIZE; age++) { struct copy_space_block *block = copy_space_block_stack_pop(&space->paged_out[age], lock); @@ -278,7 +262,7 @@ copy_space_request_release_memory(struct copy_space *space, size_t bytes) { static int copy_space_page_out_blocks_until_memory_released(struct copy_space *space) { ssize_t pending = atomic_load(&space->bytes_to_page_out); - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); while (pending > 0) { struct copy_space_block *block = copy_space_pop_empty_block(space, &lock); if (!block) break; @@ -286,7 +270,7 @@ copy_space_page_out_blocks_until_memory_released(struct copy_space *space) { pending = (atomic_fetch_sub(&space->bytes_to_page_out, COPY_SPACE_BLOCK_SIZE) - COPY_SPACE_BLOCK_SIZE); } - copy_space_lock_release(&lock); + gc_lock_release(&lock); return pending <= 0; } @@ -294,7 +278,7 @@ static ssize_t copy_space_maybe_reacquire_memory(struct copy_space *space, size_t bytes) { ssize_t pending = atomic_fetch_sub(&space->bytes_to_page_out, bytes) - bytes; - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); while (pending + COPY_SPACE_BLOCK_SIZE <= 0) { struct copy_space_block *block = copy_space_page_in_block(space, &lock); if (!block) break; @@ -303,7 +287,7 @@ copy_space_maybe_reacquire_memory(struct copy_space *space, size_t bytes) { COPY_SPACE_BLOCK_SIZE) + COPY_SPACE_BLOCK_SIZE); } - copy_space_lock_release(&lock); + gc_lock_release(&lock); return pending; } @@ -338,9 +322,9 @@ copy_space_allocator_acquire_block(struct copy_space_allocator *alloc, static int copy_space_allocator_acquire_empty_block(struct copy_space_allocator *alloc, struct copy_space *space) { - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); struct copy_space_block *block = copy_space_pop_empty_block(space, &lock); - copy_space_lock_release(&lock); + gc_lock_release(&lock); if (copy_space_allocator_acquire_block(alloc, block, space->active_region)) { block->in_core = 1; if (block->all_zeroes[space->active_region]) @@ -355,10 +339,10 @@ copy_space_allocator_acquire_empty_block(struct copy_space_allocator *alloc, static int copy_space_allocator_acquire_partly_full_block(struct copy_space_allocator *alloc, struct copy_space *space) { - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); struct copy_space_block *block = copy_space_pop_partly_full_block(space, &lock); - copy_space_lock_release(&lock); + gc_lock_release(&lock); if (copy_space_allocator_acquire_block(alloc, block, space->active_region)) { alloc->hp += block->allocated; return 1; @@ -390,9 +374,9 @@ copy_space_allocator_release_partly_full_block(struct copy_space_allocator *allo allocated - alloc->block->allocated, memory_order_relaxed); alloc->block->allocated = allocated; - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); copy_space_push_partly_full_block(space, alloc->block, &lock); - copy_space_lock_release(&lock); + gc_lock_release(&lock); } else { // In this case, hp was bumped all the way to the limit, in which // case allocated wraps to 0; the block is full. @@ -691,7 +675,7 @@ copy_space_expand(struct copy_space *space, size_t bytes) { struct copy_space_slab *slabs = copy_space_allocate_slabs(nslabs); copy_space_add_slabs(space, slabs, nslabs); - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); for (size_t slab = 0; slab < nslabs; slab++) { for (size_t idx = 0; idx < COPY_SPACE_NONHEADER_BLOCKS_PER_SLAB; idx++) { struct copy_space_block *block = &slabs[slab].headers[idx]; @@ -701,14 +685,14 @@ copy_space_expand(struct copy_space *space, size_t bytes) { reserved -= COPY_SPACE_BLOCK_SIZE; } } - copy_space_lock_release(&lock); + gc_lock_release(&lock); copy_space_reacquire_memory(space, 0); } static void copy_space_advance_page_out_queue(void *data) { struct copy_space *space = data; - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); for (int age = COPY_SPACE_PAGE_OUT_QUEUE_SIZE - 3; age >= 0; age--) { while (1) { struct copy_space_block *block = @@ -717,14 +701,14 @@ copy_space_advance_page_out_queue(void *data) { copy_space_block_stack_push(&space->paged_out[age + 1], block, &lock); } } - copy_space_lock_release(&lock); + gc_lock_release(&lock); } static void copy_space_page_out_blocks(void *data) { struct copy_space *space = data; int age = COPY_SPACE_PAGE_OUT_QUEUE_SIZE - 2; - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); while (1) { struct copy_space_block *block = copy_space_block_stack_pop(&space->paged_out[age], &lock); @@ -735,7 +719,7 @@ copy_space_page_out_blocks(void *data) { MADV_DONTNEED); copy_space_block_stack_push(&space->paged_out[age + 1], block, &lock); } - copy_space_lock_release(&lock); + gc_lock_release(&lock); } static int @@ -763,7 +747,7 @@ copy_space_init(struct copy_space *space, size_t size, int atomic, space->fragmentation_at_last_gc = 0; space->extents = extents_allocate(10); copy_space_add_slabs(space, slabs, nslabs); - struct copy_space_lock lock = copy_space_lock(space); + struct gc_lock lock = copy_space_lock(space); for (size_t slab = 0; slab < nslabs; slab++) { for (size_t idx = 0; idx < COPY_SPACE_NONHEADER_BLOCKS_PER_SLAB; idx++) { struct copy_space_block *block = &slabs[slab].headers[idx]; @@ -777,7 +761,7 @@ copy_space_init(struct copy_space *space, size_t size, int atomic, } } } - copy_space_lock_release(&lock); + gc_lock_release(&lock); gc_background_thread_add_task(thread, GC_BACKGROUND_TASK_START, copy_space_advance_page_out_queue, space); diff --git a/src/gc-lock.h b/src/gc-lock.h new file mode 100644 index 000000000..89c5f4ac0 --- /dev/null +++ b/src/gc-lock.h @@ -0,0 +1,24 @@ +#ifndef GC_LOCK_H +#define GC_LOCK_H + +#include <pthread.h> +#include "gc-assert.h" + +struct gc_lock { + pthread_mutex_t *lock; +}; + +static struct gc_lock +gc_lock_acquire(pthread_mutex_t *lock) { + pthread_mutex_lock(lock); + return (struct gc_lock){ lock }; +} + +static void +gc_lock_release(struct gc_lock *lock) { + GC_ASSERT(lock->lock); + pthread_mutex_unlock(lock->lock); + lock->lock = NULL; +} + +#endif // GC_LOCK_H diff --git a/src/nofl-space.h b/src/nofl-space.h index ebf44a524..93904aee5 100644 --- a/src/nofl-space.h +++ b/src/nofl-space.h @@ -18,6 +18,7 @@ #include "gc-align.h" #include "gc-attrs.h" #include "gc-inline.h" +#include "gc-lock.h" #include "spin.h" #include "swar.h" @@ -146,10 +147,6 @@ struct nofl_block_stack { struct nofl_block_list list; }; -struct nofl_lock { - pthread_mutex_t *lock; -}; - #define NOFL_PAGE_OUT_QUEUE_SIZE 4 struct nofl_space { @@ -208,15 +205,33 @@ struct nofl_allocator { // // When an object becomes dead after a GC, it will still have a bit set // -- maybe the young bit, or maybe a survivor bit. The sweeper has to -// clear these bits before the next collection. But, for concurrent -// marking, we will also be marking "live" objects, updating their mark -// bits. So there are four object states concurrently observable: -// young, dead, survivor, and marked. (If we didn't have concurrent -// marking we would still need the "marked" state, because marking -// mutator roots before stopping is also a form of concurrent marking.) -// Even though these states are mutually exclusive, we use separate bits -// for them because we have the space. After each collection, the dead, -// survivor, and marked states rotate by one bit. +// clear these bits before the next collection. But if we add +// concurrent marking, we will also be marking "live" objects, updating +// their mark bits. So there are four object states concurrently +// observable: young, dead, survivor, and marked. (We don't currently +// have concurrent marking, though.) Even though these states are +// mutually exclusive, we use separate bits for them because we have the +// space. After each collection, the dead, survivor, and marked states +// rotate by one bit. +// +// An object can be pinned, preventing it from being evacuated during +// collection. Pinning does not keep the object alive; if it is +// otherwise unreachable, it will be collected. To pin an object, a +// running mutator can set the pinned bit, using atomic +// compare-and-swap. +// +// For generational collectors, the nofl space supports a field-logging +// write barrier. The two logging bits correspond to the two words in a +// granule. When a field is written to, the write barrier should check +// the logged bit; if it is unset, it should try to atomically set the +// bit, and if that works, then we record the field location as a +// generational root, adding it to a sequential-store buffer. +// +// Finally, for heap-conservative collectors, nofl generally traces all +// objects in the same way, treating them as an array of conservative +// edges. But we need to know when we have an ephemeron. In that case, +// we re-use the pinned bit, because it's of no use to us anyway in that +// configuration, as all objects are pinned. enum nofl_metadata_byte { NOFL_METADATA_BYTE_NONE = 0, NOFL_METADATA_BYTE_YOUNG = 1, @@ -224,9 +239,10 @@ enum nofl_metadata_byte { NOFL_METADATA_BYTE_MARK_1 = 4, NOFL_METADATA_BYTE_MARK_2 = 8, NOFL_METADATA_BYTE_END = 16, - NOFL_METADATA_BYTE_EPHEMERON = 32, - NOFL_METADATA_BYTE_PINNED = 64, - NOFL_METADATA_BYTE_UNUSED_1 = 128 + NOFL_METADATA_BYTE_PINNED = 32, + NOFL_METADATA_BYTE_LOGGED_0 = 64, + NOFL_METADATA_BYTE_LOGGED_1 = 128, + NOFL_METADATA_BYTE_EPHEMERON = NOFL_METADATA_BYTE_PINNED, }; static uint8_t @@ -236,22 +252,9 @@ nofl_rotate_dead_survivor_marked(uint8_t mask) { return ((mask << 1) | (mask >> 2)) & all; } -static struct nofl_lock -nofl_lock_acquire(pthread_mutex_t *lock) { - pthread_mutex_lock(lock); - return (struct nofl_lock){ lock }; -} - -static void -nofl_lock_release(struct nofl_lock *lock) { - GC_ASSERT(lock->lock); - pthread_mutex_unlock(lock->lock); - lock->lock = NULL; -} - -static struct nofl_lock +static struct gc_lock nofl_space_lock(struct nofl_space *space) { - return nofl_lock_acquire(&space->lock); + return gc_lock_acquire(&space->lock); } static struct nofl_slab* @@ -440,7 +443,7 @@ nofl_block_list_pop(struct nofl_block_list *list) { static void nofl_block_stack_push(struct nofl_block_stack *stack, struct nofl_block_ref block, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { struct nofl_block_list *list = &stack->list; list->count++; GC_ASSERT(nofl_block_is_null(nofl_block_next(block))); @@ -451,7 +454,7 @@ nofl_block_stack_push(struct nofl_block_stack *stack, static struct nofl_block_ref nofl_block_stack_pop(struct nofl_block_stack *stack, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { struct nofl_block_list *list = &stack->list; struct nofl_block_ref head = nofl_block_head(list); if (!nofl_block_is_null(head)) { @@ -470,7 +473,7 @@ nofl_block_count(struct nofl_block_list *list) { static void nofl_push_unavailable_block(struct nofl_space *space, struct nofl_block_ref block, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { nofl_block_set_flag(block, NOFL_BLOCK_UNAVAILABLE); nofl_block_stack_push(nofl_block_has_flag(block, NOFL_BLOCK_PAGED_OUT) ? &space->paged_out[NOFL_PAGE_OUT_QUEUE_SIZE-1] @@ -480,7 +483,7 @@ nofl_push_unavailable_block(struct nofl_space *space, static struct nofl_block_ref nofl_pop_unavailable_block(struct nofl_space *space, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { for (int age = 0; age < NOFL_PAGE_OUT_QUEUE_SIZE; age++) { struct nofl_block_ref block = nofl_block_stack_pop(&space->paged_out[age], lock); @@ -495,21 +498,21 @@ nofl_pop_unavailable_block(struct nofl_space *space, static void nofl_push_empty_block(struct nofl_space *space, struct nofl_block_ref block, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { nofl_block_stack_push(&space->empty, block, lock); } static struct nofl_block_ref nofl_pop_empty_block_with_lock(struct nofl_space *space, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { return nofl_block_stack_pop(&space->empty, lock); } static struct nofl_block_ref nofl_pop_empty_block(struct nofl_space *space) { - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); struct nofl_block_ref ret = nofl_pop_empty_block_with_lock(space, &lock); - nofl_lock_release(&lock); + gc_lock_release(&lock); return ret; } @@ -635,19 +638,19 @@ nofl_allocator_release_partly_full_block(struct nofl_allocator *alloc, size_t hole_size = alloc->sweep - alloc->alloc; GC_ASSERT(hole_size); block.summary->fragmentation_granules = hole_size / NOFL_GRANULE_SIZE; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); nofl_block_stack_push(&space->partly_full, block, &lock); - nofl_lock_release(&lock); + gc_lock_release(&lock); nofl_allocator_reset(alloc); } static size_t nofl_allocator_acquire_partly_full_block(struct nofl_allocator *alloc, struct nofl_space *space) { - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); struct nofl_block_ref block = nofl_block_stack_pop(&space->partly_full, &lock); - nofl_lock_release(&lock); + gc_lock_release(&lock); if (nofl_block_is_null(block)) return 0; GC_ASSERT_EQ(block.summary->holes_with_fragmentation, 0); @@ -1039,11 +1042,11 @@ static void nofl_space_prepare_evacuation(struct nofl_space *space) { GC_ASSERT(!space->evacuating); struct nofl_block_ref block; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); while (!nofl_block_is_null (block = nofl_block_list_pop(&space->evacuation_targets))) nofl_push_empty_block(space, block, &lock); - nofl_lock_release(&lock); + gc_lock_release(&lock); // Blocks are either to_sweep, empty, or unavailable. GC_ASSERT_EQ(nofl_block_count(&space->partly_full.list), 0); GC_ASSERT_EQ(nofl_block_count(&space->full), 0); @@ -1164,7 +1167,7 @@ nofl_space_start_gc(struct nofl_space *space, enum gc_collection_kind gc_kind) { static void nofl_space_finish_evacuation(struct nofl_space *space, - const struct nofl_lock *lock) { + const struct gc_lock *lock) { // When evacuation began, the evacuation reserve was moved to the // empties list. Now that evacuation is finished, attempt to // repopulate the reserve. @@ -1308,7 +1311,7 @@ static void nofl_space_finish_gc(struct nofl_space *space, enum gc_collection_kind gc_kind) { space->last_collection_was_minor = (gc_kind == GC_COLLECTION_MINOR); - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); if (space->evacuating) nofl_space_finish_evacuation(space, &lock); else { @@ -1346,7 +1349,7 @@ nofl_space_finish_gc(struct nofl_space *space, } // FIXME: Promote concurrently instead of during the pause. - nofl_lock_release(&lock); + gc_lock_release(&lock); nofl_space_promote_blocks(space); nofl_space_reset_statistics(space); nofl_space_update_mark_patterns(space, 0); @@ -1363,7 +1366,7 @@ static ssize_t nofl_space_maybe_reacquire_memory(struct nofl_space *space, size_t bytes) { ssize_t pending = atomic_fetch_sub(&space->pending_unavailable_bytes, bytes) - bytes; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); while (pending + NOFL_BLOCK_SIZE <= 0) { struct nofl_block_ref block = nofl_pop_unavailable_block(space, &lock); if (nofl_block_is_null(block)) break; @@ -1372,13 +1375,15 @@ nofl_space_maybe_reacquire_memory(struct nofl_space *space, size_t bytes) { pending = atomic_fetch_add(&space->pending_unavailable_bytes, NOFL_BLOCK_SIZE) + NOFL_BLOCK_SIZE; } - nofl_lock_release(&lock); + gc_lock_release(&lock); return pending; } static inline int nofl_space_should_evacuate(struct nofl_space *space, uint8_t metadata_byte, struct gc_ref obj) { + if (gc_has_conservative_intraheap_edges()) + return 0; if (!space->evacuating) return 0; if (metadata_byte & NOFL_METADATA_BYTE_PINNED) @@ -1389,8 +1394,11 @@ nofl_space_should_evacuate(struct nofl_space *space, uint8_t metadata_byte, static inline int nofl_space_set_mark(struct nofl_space *space, uint8_t *metadata, uint8_t byte) { + // Clear logged bits when we mark: after marking, there will be no + // young objects. uint8_t mask = NOFL_METADATA_BYTE_YOUNG | NOFL_METADATA_BYTE_MARK_0 - | NOFL_METADATA_BYTE_MARK_1 | NOFL_METADATA_BYTE_MARK_2; + | NOFL_METADATA_BYTE_MARK_1 | NOFL_METADATA_BYTE_MARK_2 + | NOFL_METADATA_BYTE_LOGGED_0 | NOFL_METADATA_BYTE_LOGGED_1; atomic_store_explicit(metadata, (byte & ~mask) | space->marked_mask, memory_order_relaxed); @@ -1407,6 +1415,10 @@ nofl_space_set_nonempty_mark(struct nofl_space *space, uint8_t *metadata, static inline void nofl_space_pin_object(struct nofl_space *space, struct gc_ref ref) { + // For the heap-conservative configuration, all objects are pinned, + // and we re-use the pinned bit to identify ephemerons. + if (gc_has_conservative_intraheap_edges()) + return; uint8_t *metadata = nofl_metadata_byte_for_object(ref); uint8_t byte = atomic_load_explicit(metadata, memory_order_relaxed); if (byte & NOFL_METADATA_BYTE_PINNED) @@ -1674,7 +1686,7 @@ nofl_space_add_slabs(struct nofl_space *space, struct nofl_slab *slabs, static int nofl_space_shrink(struct nofl_space *space, size_t bytes) { ssize_t pending = nofl_space_request_release_memory(space, bytes); - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); // First try to shrink by unmapping previously-identified empty blocks. while (pending > 0) { @@ -1707,7 +1719,7 @@ nofl_space_shrink(struct nofl_space *space, size_t bytes) { } } - nofl_lock_release(&lock); + gc_lock_release(&lock); // It still may be the case we need to page out more blocks. Only evacuation // can help us then! @@ -1725,7 +1737,7 @@ nofl_space_expand(struct nofl_space *space, size_t bytes) { struct nofl_slab *slabs = nofl_allocate_slabs(nslabs); nofl_space_add_slabs(space, slabs, nslabs); - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); for (size_t slab = 0; slab < nslabs; slab++) { for (size_t idx = 0; idx < NOFL_NONMETA_BLOCKS_PER_SLAB; idx++) { uintptr_t addr = (uintptr_t)slabs[slab].blocks[idx].data; @@ -1734,7 +1746,7 @@ nofl_space_expand(struct nofl_space *space, size_t bytes) { nofl_push_unavailable_block(space, block, &lock); } } - nofl_lock_release(&lock); + gc_lock_release(&lock); nofl_space_maybe_reacquire_memory(space, 0); } @@ -1748,7 +1760,7 @@ nofl_space_advance_page_out_queue(void *data) { // items, except that we don't page out yet, as it could be that some other // background task will need to pull pages back in. struct nofl_space *space = data; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); for (int age = NOFL_PAGE_OUT_QUEUE_SIZE - 3; age >= 0; age--) { struct nofl_block_ref block = nofl_block_stack_pop(&space->paged_out[age], &lock); @@ -1756,7 +1768,7 @@ nofl_space_advance_page_out_queue(void *data) { break; nofl_block_stack_push(&space->paged_out[age+1], block, &lock); } - nofl_lock_release(&lock); + gc_lock_release(&lock); } static void @@ -1764,7 +1776,7 @@ nofl_space_page_out_blocks(void *data) { // This task is invoked by the background thread after other tasks. It // actually pages out blocks that reached the end of the queue. struct nofl_space *space = data; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); int age = NOFL_PAGE_OUT_QUEUE_SIZE - 2; while (1) { struct nofl_block_ref block = @@ -1775,7 +1787,7 @@ nofl_space_page_out_blocks(void *data) { madvise((void*)block.addr, NOFL_BLOCK_SIZE, MADV_DONTNEED); nofl_block_stack_push(&space->paged_out[age + 1], block, &lock); } - nofl_lock_release(&lock); + gc_lock_release(&lock); } static int @@ -1797,7 +1809,7 @@ nofl_space_init(struct nofl_space *space, size_t size, int atomic, space->evacuation_minimum_reserve = 0.02; space->evacuation_reserve = space->evacuation_minimum_reserve; space->promotion_threshold = promotion_threshold; - struct nofl_lock lock = nofl_space_lock(space); + struct gc_lock lock = nofl_space_lock(space); for (size_t slab = 0; slab < nslabs; slab++) { for (size_t idx = 0; idx < NOFL_NONMETA_BLOCKS_PER_SLAB; idx++) { uintptr_t addr = (uintptr_t)slabs[slab].blocks[idx].data; @@ -1812,7 +1824,7 @@ nofl_space_init(struct nofl_space *space, size_t size, int atomic, } } } - nofl_lock_release(&lock); + gc_lock_release(&lock); gc_background_thread_add_task(thread, GC_BACKGROUND_TASK_START, nofl_space_advance_page_out_queue, space);