Skip to content

Commit 45ffaf1

Browse files
Run GC if no fiber stacks are available, before expanding pool.
1 parent 3b8317e commit 45ffaf1

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

cont.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count)
554554

555555
if (!VirtualProtect(page, RB_PAGE_SIZE, PAGE_READWRITE | PAGE_GUARD, &old_protect)) {
556556
VirtualFree(allocation->base, 0, MEM_RELEASE);
557+
ruby_xfree(allocation);
557558
rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
558559
}
559560
#elif defined(__wasi__)
@@ -562,6 +563,7 @@ fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count)
562563
#else
563564
if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
564565
munmap(allocation->base, count*stride);
566+
ruby_xfree(allocation);
565567
rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
566568
}
567569
#endif
@@ -666,13 +668,23 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation)
666668
static struct fiber_pool_stack
667669
fiber_pool_stack_acquire(struct fiber_pool * fiber_pool)
668670
{
669-
struct fiber_pool_vacancy * vacancy ;
671+
struct fiber_pool_vacancy * vacancy;
672+
670673
RB_VM_LOCK_ENTER();
671674
{
672675
vacancy = fiber_pool_vacancy_pop(fiber_pool);
673676

674677
if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", (void*)fiber_pool->vacancies, fiber_pool->used);
675678

679+
// During allocation, if we run out of stacks, we may need to collect garbage to free up some stacks before trying to allocate more.
680+
if (!vacancy) {
681+
if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: no stacks available, collecting garbage\n");
682+
rb_gc();
683+
684+
// In the worst case, we garbage collect, but all fibers are reachable, so we don't free any stacks. We will try to expand the fiber pool:
685+
vacancy = fiber_pool_vacancy_pop(fiber_pool);
686+
}
687+
676688
if (!vacancy) {
677689
const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE;
678690
const size_t minimum = fiber_pool->initial_count;
@@ -681,6 +693,7 @@ fiber_pool_stack_acquire(struct fiber_pool * fiber_pool)
681693
if (count > maximum) count = maximum;
682694
if (count < minimum) count = minimum;
683695

696+
if (DEBUG)fprintf(stderr, "fiber_pool_stack_acquire: expanding fiber pool to %"PRIuSIZE" stacks\n", count);
684697
fiber_pool_expand(fiber_pool, count);
685698

686699
// The free list should now contain some stacks:

0 commit comments

Comments
 (0)