STATIC_NOINLINE void g_initialstub(struct stacklet_thread_s *thrd, stacklet_run_fn run, void *run_arg) { struct stacklet_s *result; /* The following call returns twice! */ result = (struct stacklet_s *) _stacklet_switchstack(g_initial_save_state, g_restore_state, thrd); if (result == NULL && thrd->g_source != NULL) { /* First time it returns. Only g_initial_save_state() has run and has created 'g_source'. Call run(). */ thrd->g_current_stack_stop = thrd->g_current_stack_marker; result = run(thrd->g_source, run_arg); /* Then switch to 'result'. */ check_valid(result); thrd->g_target = result; _stacklet_switchstack(g_destroy_state, g_restore_state, thrd); _check_failed("we should not return here"); abort(); } /* The second time it returns. */ }
stacklet_handle stacklet_switch(stacklet_handle target) { long stackmarker; stacklet_thread_handle thrd = target->stack_thrd; if (thrd->g_current_stack_stop <= (char *)&stackmarker) thrd->g_current_stack_stop = ((char *)&stackmarker) + 1; thrd->g_target = target; _stacklet_switchstack(g_save_state, g_restore_state, thrd); return thrd->g_source; }