mirror of
https://github.com/forth-ev/VolksForth.git
synced 2024-11-25 10:30:57 +00:00
Add the Semaphore section of tasker.md
This commit is contained in:
parent
49cf59a14c
commit
56ff1e9239
@ -261,8 +261,8 @@ corruption in case of a small stack underrun.
|
|||||||
|
|
||||||
And typically, the dictionary of any task but the console task will be empty,
|
And typically, the dictionary of any task but the console task will be empty,
|
||||||
as that is where the outer interpreter is running which usally populates the
|
as that is where the outer interpreter is running which usally populates the
|
||||||
dictionary through definitions. However, `dp` is a user variable, so each task
|
dictionary through definitions. However, `DP` is a user variable, so each task
|
||||||
has its own `here`, and if a task calls `allot`, the memory will be allocated
|
has its own `HERE`, and if a task calls `ALLOT`, the memory will be allocated
|
||||||
in its own dictionary.
|
in its own dictionary.
|
||||||
|
|
||||||
#### Tasks' user areas
|
#### Tasks' user areas
|
||||||
@ -303,6 +303,57 @@ robin loop consists of
|
|||||||
└ <- <- <- <- <-- <- <- <┘
|
└ <- <- <- <- <-- <- <- <┘
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Semaphores and LOCK
|
||||||
|
|
||||||
|
A problem that has not yet been mentioned: what happens when two tasks want to
|
||||||
|
print or access the disk drive simultaneously? Obviously, I/O devices may
|
||||||
|
at any time be used by only one task. This is achieved using Semaphores:
|
||||||
|
|
||||||
|
```
|
||||||
|
Create disp 0,
|
||||||
|
: newtype disp lock type disp unlock;
|
||||||
|
```
|
||||||
|
|
||||||
|
This has the following effect:
|
||||||
|
|
||||||
|
If two tasks call `NEWTYPE` at the same time, still only task at a time will
|
||||||
|
get to run `TYPE`, regardless of how many `PAUSE` are included in `TYPE`.
|
||||||
|
The phrase `DISP LOCK` will set up a barrier after the first task that performs
|
||||||
|
it, like switching a traffic light to red, and lets no other task pass.
|
||||||
|
The other task is held until the first task switches the traffic light to
|
||||||
|
green again via `DISP UNLOCK`. Then one (!) other task can pass the traffic
|
||||||
|
light, switching it red again, and so on.
|
||||||
|
|
||||||
|
By the way, the task that switched the traffic lights to red will not be
|
||||||
|
stopped by another `DISP LOCK` but will be let through. This is
|
||||||
|
necessary since `TYPE` could also contain a `DISP LOCK`.
|
||||||
|
(It doesn't in the above example, but it is conceivable.)
|
||||||
|
|
||||||
|
The implementation looks like this:
|
||||||
|
(Remember that every task is uniquely identifiable by the its user area
|
||||||
|
address.)
|
||||||
|
|
||||||
|
`DISP` is the so-called Semaphore; it must have the initial value 0.
|
||||||
|
|
||||||
|
`LOCK` looks at the Semaphore:
|
||||||
|
If it is zero, then the currently asctive task (i.e. its user area address)
|
||||||
|
is written to the semaphore, and the task may continue on its way.
|
||||||
|
If the value of the semaphore is the active task, then it may continue, too.
|
||||||
|
But if the value of the semaphore deviates from the active task's user area
|
||||||
|
address, then another task is active behind the traffic light, and the task
|
||||||
|
must `PAUSE` until the light turns green again, i.e. until the semaphore is
|
||||||
|
zero.
|
||||||
|
|
||||||
|
`UNLOCK` has nothing more to do than to set the value of the semaphore back to
|
||||||
|
zero.
|
||||||
|
|
||||||
|
`BLOCK` and `BUFFER` are, by the way, secured in this way for use by several
|
||||||
|
tasks:
|
||||||
|
only one task can request the loading of a blocks from the diskette at any given
|
||||||
|
time.
|
||||||
|
Whether `TYPE`, `EMIT`, etc. are also secured depends on their implementation -
|
||||||
|
`TYPE`, `EMIT`, etc are essentially deferred words with different possible
|
||||||
|
implementations.
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user