Previous: Multitasker, Up: Multitasker [Contents][Index]
Tasks can be created with newtask
or newtask4
with a
given amount of stack space (either all the same or each stack’s size
specified); these tasks neet to be activate
d or send an
xt through initiate
. Tasks can stop
themselves
when they are done or wait for new instructions.
doc-newtask doc-task doc-execute-task doc-stacksize doc-newtask4 doc-stacksize4 doc-activate doc-pass doc-initiate doc-pause doc-restart doc-halt doc-stop doc-stop-ns
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.
Aside from the user variables that are already defined in the kernel, tasks may want to have user values and user defers, optain the offset of a user variable, or the address of those related to another task to initialize that task’s user area.
UValue
( "name" – ) unknown “UValue”
doc-udefer doc-user’ doc-’s
Semaphores can only be aquired by one thread, all other threads have to wait until the semapohre is released.
doc-semaphore doc-lock doc-unlock
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.
doc-critical-section
Atomic operations can be used to synchronize tasks without using slow OS primitives.
!@
( u1 a-addr – u2 ) gforth-experimental “store-fetch”
load u2 from a_addr, and store u1 there, as atomic operation
+!@
( u1 a-addr – u2 ) gforth-experimental “add-store-fetch”
load u2 from a_addr, and increment this location by u1, as atomic operation
?!@
( unew uold a-addr – uprev ) gforth-experimental “question-store-fetch”
load uprev from a_addr, compare it to uold, and if equal, store unew there, as atomic operation
barrier
( – ) gforth-experimental “barrier”
Insert a full memory barrier
Gforth implements executable message queues for event driven programs:
you send instructions to other tasks, enclosed in <event
and
event>
; the entire event sequence is executed atomically. 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
messages 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. The
message queue is queried when you stop
a task, or when you
check for events with ?events
. You can define a maximum of 256
different events.
doc-<event doc-event> doc-event: doc-?events doc-event-loop doc-elit, doc-e$, doc-eflit,
The naming conventions for events is :>
name.
The pthreads library also provides conditional variables, which allow to wait for a condition. Using the message queue is generally preferred.
doc-cond
pthread_cond_signal
( cond – r ) gforth-experimental “pthread_cond_signal”
pthread_cond_broadcast
( cond – r ) gforth-experimental “pthread_cond_broadcast”
pthread_cond_wait
( cond mutex – r ) gforth-experimental “pthread_cond_wait”
pthread_cond_timedwait
( cond mutex abstime – r ) gforth-experimental “pthread_cond_timedwait”
Previous: Multitasker, Up: Multitasker [Contents][Index]