The 68xxx multitasker follows the model introduced with the v6.1 compilers. A few extensions are also provided.
0 equ test-multi? \ true to compile test code
If not previously defined, TEST-MULTI? is set to zero and test code is not compiled.
|
This structure is allocated at the start of the USER area. Consequently the TCB of the current task is given by UP.
struct /TCB \ -- size
The structure used by the code that matches the description above.
init-u0 constant main \ -- addr ; tcb of main task
Returns the base address of the main task's USER area.
0 value multi? \ -- flag ; true if tasker enabled
Returns true if the tasker is enabled.
: single \ -- ; disable scheduler
Disable scheduler.
: multi \ -- ; enable scheduler
Enable scheduler.
CODE pause \ -- ; the scheduler
The software scheduler itself.
code status \ -- task-status
Returns the current task's status cell, but with the run bit masked out.
CODE restart \ task -- ; mark task TCB as running
Sets the RUN bit in the task's status cell.
CODE halt \ task# -- ; reset running bit in TCB
Clears the RUN bit in the task's status cell.
: stop \ -- ; halt oneself
HALT's the current task, and executes PAUSE.
Event handling is only compiled if the equate EVENT-HANDLER? is set non-zero in the control file.
: set-event \ task -- ; set event trigger in task TCB
Set the event trigger in task TCB.
: event? \ task -- flag ; true if task had event
Returns true if true if task has received an event trigger which has not been cleared yet.
: clr-event-run \ -- ; reset own EVENT_RUN flag
Reset the current task's EVENT_RUN flag.
: to-event \ xt task -- ; define action of a task
Sets XT as the event handler for the task.
Message handling is only compiled if the equate MESSAGE-HANDLER? is set non-zero in the control file.
: msg? \ task -- flag ; true if task has message
Returns true if task has received a message.
: send-message \ addr task -- ; send message to task
Send a message to a task.
: get-message \ -- addr task ; wait for any message
Wait for any message and return the message and the task it came from.
: wait-event/msg \ -- ; wait for message or event trigger
Wait for a message or an event trigger.
code init-task \ xt task -- ; Initialise a task stack
Initialise a task's stack before running it and set it to execute the word whose XT is given.
: add-task \ task -- ; insert into list
Add the task to the list of tasks after the current task.
: sub-task \ task -- ; remove task from chain
Remove the task from the task list.
: initiate \ xt task -- ; start task from scratch and run it
Start the given task executing the word whose XT is given, e.g.
['] <name> <task> INITIATE
: sleeper \ xt task -- ; start task from scratch, but leave it HALTed
Use in the form:
|
to put a task on the active task list, but as if HALTed. SLEEPER allows you to make a task ready for waking up later, perhaps by another task. This avoids having to put STOP as the first word in a task. Note that SLEEPER does not call PAUSE. See also INITIATE.
: terminate \ task -- ; stop task, and remove from list
Stop a task, and remove it from the list.
: init-multi \ -- ; initialisation with multi-tasking
Initialise the multitasker and start it. If tasking is selected by setting the equate TASKING? in the control file, KERNEL62.FTH will automatically run this word. Make sure that your initialisation code includes INIT-MULTI or your code will crash.
: his \ task uservar -- addr ; produce address of user var in another task
Given a task id and a USER variable, returns the address of that variable in the given task. This word is used to set up USER variables in other tasks.
The semaphore code is only compiled if the equate SEMAPHORES? is set non-zero in the control file.
A SEMAPHORE is an extended variable used for signalling between tasks, and for resource allocation. The counter field is used as a count of the number of times the resource may be used, and the arbiter field contains the TCB of the task that last gained access. This field can be used for priority arbitration and deadlock detection/arbitration.
: semaphore \ -- ; -- addr [child]
Creates a semaphore which returns its address at runtime. Use in the form:
Semaphore <name>
: signal \ addr --
SIGNAL increments the counter field of a semaphore, indicating either that another item has been allocated to the resource, or that it is available for use again, 0 indicating in use by a task REQUEST waits until the counter field of a semaphore is non-zero, and then decrements the counter field by one. This allows the semaphore to be used as a COUNTED semaphore. For example a character buffer may be used where the semaphore counter shows the number of available characters. Alternatively the semaphore may be used purely to share resources. The semaphore is initialised to one. The first task to REQUEST it gains access, and all other tasks must wait until the accessing task SIGNALs that it has finished with the resource.
TASK <name> builds a named task user area. The action of a task is assigned and the task started by the word INITIATE
['] <action> <task> INITIATE
START: is used inside a colon definition. The code before START: is the task's initialisation, performed by the current task. The code after START: up to the closing ; is the action of the task. For example:
|
All tasks must run in an endless loop, except for initialisation code. When RUN-FOO is executed, the code after START: is set up as the action of task FOO and started. RUN-FOO then exits.
If you want to perform additional actions after starting the task, you should use INITIATE to start the task.
variable task-chain \ -- addr
Anchors list of all tasks created by TASK and friends.
: task \ -- ; -- task ; TASK <name> builds a task
Note that the cross-interpreter's version of TASK has been modified from v6.2 onwards to leave the current section as CDATA.
: task \ -- ; -- task ; TASK <name> builds a task
Creates a new task and data area, returning the address of the user area at run time. The task is also linked into the task chain anchored by TASK-CHAIN.
: start: \ task -- ; exits from caller
Used inside a colon definition. The code following START: up to the ending semi-colon forms the action of the task. The word containing START: finishes at START:.
: .task \ task --
Display task's name if it has one.
: .tasks \ task -- ; display all task names
Display all the tasks anchored by TASK-CHAIN.
: .running \ --
Display running tasks.