SML_PRIMITIVE void sml_control_suspend() { struct sml_control *control = CONTROL(); control->frame_stack_top = CALLER_FRAME_END_ADDRESS(); control_suspend(control); }
SML_PRIMITIVE void sml_enter() { struct sml_control *control = tlv_get(current_control); control_enter(control); assert(control->frame_stack->top == CALLER_FRAME_END_ADDRESS()); control->frame_stack->top = NULL; }
SML_PRIMITIVE void sml_push_fp() { struct sml_control *control = CONTROL(); if (control->frame_stack_top_override != NULL) FATAL((0, "sml_push_fp overfull")); control->frame_stack_top_override = CALLER_FRAME_END_ADDRESS(); }
SML_PRIMITIVE void sml_unsave() { struct sml_control *control = tlv_get(current_control); #ifndef WITHOUT_MULTITHREAD assert(IS_ACTIVE(load_relaxed(&control->state))); #endif /* !WITHOUT_MULTITHREAD */ assert(control->frame_stack->top == CALLER_FRAME_END_ADDRESS()); control->frame_stack->top = NULL; }
SML_PRIMITIVE void sml_start(void **arg) { struct frame_stack_range *range = (void*)arg; struct sml_control *control = tlv_get_or_init(current_control); range->bottom = CALLER_FRAME_END_ADDRESS(); range->top = NULL; if (control == NULL) { control_start(range); } else { control_enter(control); range->next = control->frame_stack; control->frame_stack = range; } }
SML_PRIMITIVE void sml_end() { struct sml_control *control = tlv_get(current_control); #ifndef WITHOUT_MULTITHREAD assert(IS_ACTIVE(load_relaxed(&control->state))); #endif /* !WITHOUT_MULTITHREAD */ assert(control->frame_stack->bottom == CALLER_FRAME_END_ADDRESS()); control->frame_stack = control->frame_stack->next; if (control->frame_stack) { control_leave(control); } else { control_destroy(control); } }
SML_PRIMITIVE void sml_control_finish() { struct sml_control *control = CONTROL(); void **frame_end = CALLER_FRAME_END_ADDRESS(); short *layout; if (control->frame_stack_bottom == frame_end) { DBG(("CONTROL_FINISH %p", control)); control_suspend(control); control_finalize(control); } else { layout = lookup_stack_layout(FRAME_CODE_ADDRESS(frame_end)); ASSERT(layout != NULL); ASSERT(NUM_ROOTS(layout) > 0); control->frame_stack_top = frame_end[ROOTS(layout)[0]]; control_suspend(control); } }
SML_PRIMITIVE void sml_control_start() { struct sml_control *control = CONTROL(); void **frame_end = CALLER_FRAME_END_ADDRESS(); short *layout; if (control != NULL) { control_resume(control); layout = lookup_stack_layout(FRAME_CODE_ADDRESS(frame_end)); ASSERT(layout != NULL); ASSERT(NUM_ROOTS(layout) > 0); frame_end[ROOTS(layout)[0]] = control->frame_stack_top; control->frame_stack_top = frame_end; return; } control = xmalloc(sizeof(struct sml_control)); control->state = RUN; #ifdef MULTITHREAD if (pthread_mutex_init(&control->state_lock, NULL) != 0) sml_sysfatal("pthread_mutex_init failed"); if (pthread_cond_init(&control->state_cond, NULL) != 0) sml_sysfatal("pthread_cond_init failed"); #ifdef CONCURRENT control->phase = ASYNC; #endif /* CONCURRENT */ #endif /* MULTITHREAD */ control->frame_stack_top_override = NULL; control->frame_stack_top = frame_end; control->frame_stack_bottom = frame_end; control->tmp_root[0] = NULL; control->tmp_root[1] = NULL; control->heap = sml_heap_thread_init(); control->exn = sml_exn_init(); SET_CONTROL(control); attach_control(control); DBG(("START THREAD %p", control)); }
SML_PRIMITIVE void sml_check() { assert(tlv_get(current_control)->frame_stack->top == NULL); sml_check_internal(CALLER_FRAME_END_ADDRESS()); }