Previous: Multitasker, Up: Multitasker [Contents][Index]
newtask
stacksize – task unknown “newtask”
creates a task, uses stacksize for stack, rstack, fpstack, locals
task
stacksize "name" – SwiftForth “task”
create a named task with stacksize stacksize
execute-task
xt – task unknown “execute-task”
create a new task task and initiate it with xt
stacksize
– n unknown “stacksize”
stacksize for data stack
newtask4
dsize rsize fsize lsize – task unknown “newtask4”
creates a task, each stack individually sized
stacksize4
– dsize fsize rsize lsize unknown “stacksize4”
This gives you the system stack sizes
activate
task – unknown “activate”
activates a task. The remaining part of the word calling
activate
will be executed in the context of the task.
pass
x1 .. xn n task – unknown “pass”
activates task, and passes n parameters from the data stack
initiate
xt task – unknown “initiate”
pass an xt to a task (VFX compatible)
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.
restart
task – unknown “restart”
Wake a task
halt
task – unknown “halt”
Stop a task
stop
– unknown “stop”
stops the current task, and waits for events (which may restart it)
stop-ns
timeout – 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.
Semaphores can only be aquired by one thread, all other threads have to wait until the semapohre is released.
semaphore
"name" – gforth “semaphore”
create a named semaphore "name" \\ "name"-execution: ( – semaphore )
lock
semaphore – unknown “lock”
lock the semaphore
unlock
semaphore – 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.
critical-section
xt semaphore – unknown “critical-section”
implement a critical section that will unlock the semaphore even in case there’s an exception within.
Experimental atomic operations
!@
u1 a-addr – u2 gforth “store-fetch”
load u2< from a_addr<, and store u1< there, as atomic operation
+!@
u1 a-addr – u2 gforth “add-store-fetch”
load u2< from a_addr<, and increment this location by u1<, as atomic operation
?!@
unew uold a-addr – uprev gforth “question-store-fetch”
load uprev< from a_addr<, compare it to uold<, and if equal, store unew< there, as atomic operation
barrier
– gforth “barrier”
Insert a 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.
<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.
If name
is invoked, the event gets assembled to the event buffer.
If the event name
is received, the Forth definition
that follows the event declaration is executed.
?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
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.
cond
"name" – gforth “cond”
create a named condition
pthread_cond_signal
unknown unknown “pthread_cond_signal”
pthread_cond_broadcast
unknown unknown “pthread_cond_broadcast”
pthread_cond_wait
unknown unknown “pthread_cond_wait”
pthread_cond_timedwait
unknown unknown “pthread_cond_timedwait”
Previous: Multitasker, Up: Multitasker [Contents][Index]