User-Level Native Thread Primitives (GThread) Library White Paper (G06.27+, H06.03+, J06.03+)
User-Level Native Thread Primitives (GThread Library) 02/15/2012
540065-004 Page 36 of 44
Thread^SwapOut(CTh) swaps out the current thread, puts it to sleep, and awakens the main thread
(unthreaded code):
IF (GTH_STACK_USED_(CTh) > GTH_ALLOCATED_SIZE_(CTh)) THEN
{deallocate current swap area}
newLen := GTH_STACK_USED_(CTh) + room to grow;
NewAddr := {allocate new swap area with newLen};
GTH_SET_ALLOCATION_(CTh, newAddr, newLen);
GTH_STACK_SAVE_(CTh);
{handle possible error return}
@CurThread := {null value}; -- indicate unthreaded context
GTHREAD_LONGJMP_(MainCB,1d,GTH_NULL_PROCADDR_);
Dispatch a thread:
Thread^Dispatch() is the procedure to run all ready threads; it is called from the unthreaded master
code. (The caveat for GTHREAD_SETJMP_ could apply to this procedure, because its loop might
change local state after the GTHREAD_SETJMP_ call.)
INT .EXT NextThread (ThreadImp^Struct);
-- Suspend the Main (unthreaded) context (no swap-out required)
IF GTHREAD_SETJMP_(MainCB,GTH_NULL_PROCADDR) = 0d THEN
IF (GTHREAD_MAINCONTEXT_CHECK_(MainCB) > 0d) THEN
-- Presumably Swapped-Master initialization
IF GTHREAD_ORIGIN_SET_() THEN
... -- Error: unthreaded master stack is too deep
GTH_STACK_USED_DETAIL_ can be invoked here to determine if the mem or
reg stack is too deep. If this information indicates additional resting space is needed
for the principal stacks, one can invoke GTHREAD_ORIGIN_SET_MOD_, rather
than GTHREAD_ORIGIN_SET_, to modify the unthreaded resting stack space.
ELSE RETURN; -- from initialization call
WHILE {there's some thread ready} DO
BEGIN
@NextThread := {next thread to run};
-- Adjust environment and invoke Thread^SwapIn to swap in and awaken the target thread:
GTHREAD_SWAPIN_SETUP_(NextThread,Thread^SwapIn);
-- Does not return; Thread^SwapOut LONGJMPs to top of loop.
END;
Thread^SwapIn(NextThread) readies a thread for execution and activates it: