home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
forth
/
compiler
/
fpc
/
source
/
multask.seq
< prev
next >
Wrap
Text File
|
1991-02-19
|
7KB
|
170 lines
\ MULTASK.SEQ Multi tasking code for Forth.
PREFIX
ONLY FORTH ALSO DEFINITIONS
DECIMAL
comment:
The MultiTasker is loaded as an application on top of the
regular Forth System. There is support for it in the nucleus
in the form of USER variables and PAUSEs inserted inside of
KEY EMIT and BLOCK. The Forth multitasking scheme is
co-operative instead of interruptive. All IO operations cause
a PAUSE to occur, and the multitasking loop looks around at
all of the current task for something to do.
Modified by Tom Zimmer to work with F-PC, which needs to save the ES
register along with IP. - 2/29/88 -
NOTICE !! This multi tasking DOES NOT SUPPORT MULTIPLE USERS !!!
There are a significant number of things what will have to be changed
in this Forth system to support multi user, like the editor would have
to be re-written, ect. So I am not supporting multi user, only
background processing.
Background processing MAY NOT do any compiling, compile, like VARIABLE,
or CREATE, ect. at *** RUNTIME ***. 06/06/88 13:58
YDP and XDP are NOT user variables.
TJZ 02/19/91 20:29 - Fixed a couple of bugs in multi-tasking that
prevented FSAVEd systems from running because multi-tasking was not
relocatable. It is now!. Of course there was a small performance penalty.
comment;
CODE (PAUSE) ( -- )
\ PUSH ES \ Push ES, IP, and RP \ tjz 02/19/91 remove
mov ax, es \ tjz 02/19/91 added
sub ax, xseg \ tjz 02/19/91 added
push ax \ tjz 02/19/91 added
PUSH IP
PUSH RP
MOV BX, UP \ make BX point to user area
MOV 0 [BX], SP \ save SP in user area offset 0
ADD BX, # 4 \ adjust BX to point to LINK
ADD BX, 0 [BX] \ Add value in LINK to BX, pointing it to
\ next tasks user area offset 0
ADD BX, # 2 \ bump BX 2 to point to ENTRY
JMP BX \ jump to next tasks entry point
END-CODE
CODE RESTART ( -- )
POP BX \ pop address of where we came from
MOV AX, # -4
ADD BX, AX \ adjust to beginning of user area
MOV UP BX \ set UP to point to begin of user area
POP AX \ pop off old PC
POPF \ restore status register
MOV SP, 0 [BX] \ restore SP (stack pointer)
POP RP \ restore RP, IP, and ES
POP IP
pop ax \ tjz 02/19/91 added
add ax, xseg \ tjz 02/19/91 added
mov es, ax \ tjz 02/19/91 added
\ POP ES \ tjz 02/19/91 removed
NEXT END-CODE
$0E9 CONSTANT INT#
: LOCAL ( base addr -- addr' ) UP @ - + ;
: @LINK ( -- addr ) LINK DUP @ + 2+ ;
: !LINK ( addr -- ) LINK 2+ - LINK ! ;
: SLEEP ( addr -- ) $0E990 SWAP ENTRY LOCAL ! ;
: WAKE ( addr -- ) $0E9CD SWAP ENTRY LOCAL ! ;
: STOP ( -- ) UP @ SLEEP PAUSE ;
: SINGLE ( -- )
$0E9 ['] PAUSE C! \ set JMP in PAUSE
>NEXT ['] PAUSE >BODY - \ get offset to NEXT
['] PAUSE 1+ ! ; \ store in PAUSE + 1
CODE MULTI ( -- )
MOV ' PAUSE # $0E9
MOV BX, # ' (PAUSE) ' PAUSE 3 + - \ relative I hope!
MOV ' PAUSE 1+ BX
MOV BX, # ' RESTART
MOV AX, DS
PUSH AX
SUB AX, AX MOV DS, AX
MOV AX, CS MOV INT# 4 * 2+ AX
MOV INT# 4 * BX
POP AX
MOV DS, AX NEXT
END-CODE
UP @ WAKE ENTRY !LINK
: ?MULTI ( -- f1 ) \ f1 = true if MULTI tasking
['] (PAUSE) ['] PAUSE @REL>ABS = ;
: TASK: ( size -- )
CREATE TOS HERE #USER @ CMOVE ( Copy the USER Area )
@LINK UP @ -ROT HERE UP ! !LINK ( I point where he did)
DUP HERE + DUP RP0 ! 100 - SP0 ! SWAP UP !
HERE ENTRY LOCAL !LINK ( He points to me)
HERE #USER @ + HERE DP LOCAL !
HERE SLEEP ALLOT ;
: SET-TASK ( ES ip task -- ) \ NOTE: both ES and IP are passed
\ to SET-TASK.
>R SWAP R>
DUP SP0 LOCAL @ \ Top of Stack
\ 2- ROT OVER ! \ Initial ES \ tjz 02/19/91 removed
2- ROT xseg @ - OVER ! \ Initial ES \ tjz 02/19/91 added
2- ROT OVER ! \ Initial IP
2- OVER RP0 LOCAL @ OVER ! \ Initial RP
SWAP TOS LOCAL ! ;
: ACTIVATE ( task -- )
DUP
2R> ROT SET-TASK WAKE ;
: BACKGROUND: ( -- )
400 TASK:
XHERE @LINK 2- \ get address of new task, note that
\ XHERE returns SEGMENT and OFFSET,
\ which is used by SET-TASK
SET-TASK !CSP ] ;
comment:
Here is a sample of how to create a background task that will do a
listing of the current file, with the hypothetical word FUNCTION1. The
task MYTASK is created with the default function FUNCTION1 assigned to it.
Next we define a word MYTASK-THIS, what changes the function assigned to
MYTASK to perform FUNCTION2. This allows us to change the function a
task performs without having to define a new task. In each case, the
task is stopped after its assigned FUNCTION is performed.
background: mytask function1 stop ;
: mytask-this mytask activate function2 stop ;
This next example defines a variable, and a routine which increments
the variable in the background. Notice that the program is an infinite
loop, and will only stop when put to sleep, or when multi tasking is
turned off with SINGLE. This example will actually work, you might try
typing it into a file and loading it.
variable counts
background: counter begin pause incr> counts
again ;
MULTI COUNTER WAKE \ start up the COUNTER task
\ COUNTER SLEEP \ put the COUNTER task to sleep
\ SINGLE \ disable multi tasking
comment;
ONLY FORTH ALSO DEFINITIONS