activates a task. The remaining part of the word calling
activate will be executed in the context of the task.

passx1 .. xn n task – unknown “pass”

activates task, and passes n parameters from the data stack

pause– unknown “pause”

voluntarily switch to the next waiting task (pause is
the traditional cooperative task switcher; in the pthread
multitasker, you don't need pause for cooperation, but
you still can use it e.g. when you have to resort to polling
for some reason). This also checks for events in the queue.

waketask – unknown “wake”

Wake a task

sleeptask – unknown “sleep”

Stop a task

stop– unknown “stop”

stops the current task, and waits for events (which may restart it)

stop-nstimeout – unknown “stop-ns”

Stop with timeout (in nanoseconds), better replacement for ms

UValue"name" – unknown “UValue”

Define a per-thread value

UDefer"name" – unknown “UDefer”

Define a per-thread deferred word

user''user' – n unknown “user”'

USER' computes the task offset of a user variable

A cooperative multitasker can ensure that there is no other task
interacting between two invocations of pause. Pthreads however
are really concurrent tasks (at least on a multi-core CPU), and
therefore, several techniques to avoid conflicts when accessing the same
resources.

5.25.1.1 Semaphores

Semaphores can only be aquired by one thread, all other threads have to
wait until the semapohre is released.

sema"name" – gforth “sema”

create a named semaphore

lockaddr – unknown “lock”

lock the semaphore

unlockaddr – unknown “unlock”

unlock the semaphore

The other approach to prevent concurrent access is the critical section.
Here, we implement a critical section with a semaphore, so you have to
specify the semaphore which is used for the critical section. Only
those critical sections which use the same semaphore are mutually
exclusive.

c-sectionxt addr – unknown “c-section”

implement a critical section that will unlock the semaphore
even in case there's an exception within.

5.25.1.2 Message Queues

Gforth implements executable message queues: you send instructions to
other tasks, which they will execute as atomic sequence when they are
enclosed in <event and event>. You can pass integers,
floats, and strings (only the addresses, so treat the string as
read-only after you have send it to another task). The instructions you
send are defined with event:name, which, when invoked,
will add the code for its execution to the message queue, and when
recieved, will execute the code following.

<event– unknown “<event”

starts a sequence of events.

event>task – unknown “event>”

ends a sequence and sends it to the mentioned task

event:"name" – unknown “event:”

defines an event and the reaction to it as Forth code

?events– unknown “?events”

checks for events and executes them

event-loop– unknown “event-loop”

Tasks that are controlled by sending events to them should
go into an event-loop

elit,x – unknown “elit,”

sends a literal

e$,addr u – unknown “e$,”

sends a string (actually only the address and the count, because it's
shared memory

eflit,x – unknown “eflit,”

sends a float

5.25.1.3 Conditions

The pthreads library also provides conditional variables, which allow to
wait for a condition. Using the message queue is generally preferred.