From 196f41c705f1a4942a0591de768b2b80b032bbc0 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sun, 3 Jun 2018 17:09:40 -0700 Subject: libpulp: always swap contexts In cases where the run queue was empty, the trampoline context would immediately enter the caller context. Then the trampoline would be reused again without being re-setup. This seemed to work fine on Linux but was causing bus errors on OSX. So instead now enter_context never used and contexts are always swapped to preserve the state of the context being left, which seems to have fixed the problem on OSX. --- src/pulp.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src/pulp.c') diff --git a/src/pulp.c b/src/pulp.c index ee32b7c..2a25965 100644 --- a/src/pulp.c +++ b/src/pulp.c @@ -290,16 +290,23 @@ static void destroy_context(pulp_context_t *context) * * Note that though this is coded as an infinite loop, pulp_schedule()'s * default target is pulp->caller_context. When the run queue is drained, the - * caller context is entered, and pulp_tick() returns. + * caller context is swapped with the trampoline, and pulp_tick() returns. */ static void trampoline(pulp_t *pulp) { assert(pulp); + /* note any time the trampoline is entered with a non-NULL + * pulp->current, it's assumed to be an exited fiber situation @ + * pulp->current. So anything swapping to trampoline_context outside + * of the fiber cleanup path must either set pulp->current to NULL or + * be a fiber return/destroy path. + */ for (;;) { if (pulp->current) { destroy_context(&pulp->current->context); put_current_fiber(pulp, &pulp->fibers.free); + pulp->current = NULL; } pulp_schedule(pulp); @@ -383,6 +390,7 @@ static void expire_alarms(pulp_t *pulp) static void pulp_schedule(pulp_t *pulp) { pulp_context_t *target_context = &pulp->caller_context; + pulp_context_t *source_context = &pulp->trampoline_context; pulp_fiber_t *current; assert(pulp); @@ -390,15 +398,15 @@ static void pulp_schedule(pulp_t *pulp) current = pulp->current; pulp->current = NULL; - if (!list_empty(&pulp->fibers.run)) { + if (!list_empty(&pulp->fibers.run) && !pulp->exited) { set_current_fiber(pulp, &pulp->fibers.run); target_context = &pulp->current->context; } if (current) - swap_context(¤t->context, target_context); - else - enter_context(target_context); + source_context = ¤t->context; + + swap_context(source_context, target_context); } @@ -497,9 +505,10 @@ void pulp_run(pulp_t *pulp) void pulp_exit(pulp_t *pulp) { assert(pulp); + assert(pulp->current); pulp->exited = 1; - enter_context(&pulp->caller_context); + swap_context(&pulp->current->context, &pulp->trampoline_context); } -- cgit v1.2.3