\ Load Screen for the MultiTasker 5 /15/88ONLY FORTH ALSO DEFINITIONS NEED @INT 1 4 +THRU CR .( MultiTasker Loaded ) ONLY FORTH ALSO DEFINITIONS EXIT 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 TYPE 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. \ Multitasking low level 27JAN86GEBCODE (PAUSE) (S -- ) BX PUSH IP PUSH RP PUSH UP #) BX MOV SP 0 [BX] MOV 4 [BX] BX ADD 6 # BX ADD BX JMP END-CODE CODE RESTART (S -- ) BX POP -4 # BX ADD BX UP #) MOV AX POP AX POP 0 [BX] SP MOV STI RP POP IP POP BX POP NEXT END-CODE \ Manipulate Tasks 5 /15/88HEX 80 CONSTANT INT# : LOCAL (S base addr -- addr' ) UP @ - + ; : @LINK (S -- addr ) LINK DUP @ + 2+ ; : !LINK (S addr -- ) LINK 2+ - LINK ! ; : SLEEP (S addr -- ) E990 SWAP ENTRY LOCAL ! ; : WAKE (S addr -- ) 80CD SWAP ENTRY LOCAL ! ; : STOP (S -- ) UP @ SLEEP PAUSE ; : SINGLE (S -- ) ['] PAUSE 1+ OFF ; 2VARIABLE OLDINT : MULTI (S -- ) [ ' (PAUSE) ' PAUSE 3 + - ] LITERAL ['] PAUSE 1+ ! INT# @INT OLDINT 2! ['] RESTART CSEG INT# !INT ; UP @ WAKE ENTRY !LINK DECIMAL : MULTI.BYE OLDINT 2@ INT# !INT (BYE) ; ' MULTI.BYE IS BYE \ Activate a Task 5 /15/88: TASK: (S 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 ! not multi-user !!!!!!!!! HERE SLEEP ALLOT ; : SET-TASK (S ip task -- ) DUP SP0 LOCAL @ ( Top of Stack ) 2- ROT OVER ! ( Initial IP ) 2- OVER RP0 LOCAL @ OVER ! ( Initial RP ) SWAP TOS LOCAL ! ; : ACTIVATE (S task -- ) R> OVER SET-TASK WAKE ; \ Create a Background Task 5 /15/88: BACKGROUND: (S -- ) 400 TASK: HERE @LINK 2- ( get address of new task ) SET-TASK !CSP COMPILER ; \S background: spooler 1 capacity show stop ; : spool-this spooler activate 3 15 [ shadow ] show stop ; variable counts background: counter begin pause 1 counts +! again ; \ Examples 5 /15/88See BACKGROUND: and its shadow for spooler and counter tasks. To enable spooler, once defined, type MULTI. MULTI starts the multi-tasker loop running. SINGLE stops it. Then type SPOOLER WAKE to start the spooler task. To put the spooler on hold, use SPOOLER SLEEP To restart it, use SPOOLER WAKE In general, executing the name of a task leaves the address of its user area on the stack. Words like sleep and wake use that address. \ Multitasking low level 5 /15/88(PAUSE) (S -- ) Puts a task to sleep by storing the IP and the RP on the parameter stack. It then saves the pointer to the parameter stack in the user area and jumps to the code pointed at by LINK, switching tasks. RESTART (S -- ) Sets the user pointer to point to a new user area and restores the parameter stack that was previously saved in the USER area. Then pops the RP and IP off of the stack and resumes execution. The inverse of PAUSE. \ Manipulate Tasks 5 /15/88INT# The software interrupt number to use on the 8086 LOCAL Map a User variable from the current task to another task@LINK Return a pointer the the next tasks entry point !LINK Set the link field of the current task (perhaps relative)SLEEP makes a task pause indefinitely. WAKE lets a task start again. STOP makes a task pause indefinitely. SINGLE removes the multi-tasker's scheduler/dispatcher loop. MULTI installs the multi-tasker's scheduler/dispatcher loop. By patching the appropriate INT vector and enabling PAUSE. \ Activate a Task 5 /15/88TASK: Name, initialize, and allocate a new task. Copy the USER Area. I point to where he pointed. He points to me. Set initial stack pointers. Set dictionary pointer. Make task ready to execute. Allocate task in host dictionary. SET-TASK assigns an existing task to the code at ip. Get top of stack of the task to be used. Put IP and RP values on its stack. Set its saved stack pointer. ACTIVATE assigns an existing task to the following code, and makes it ready to execute. \ Create a Background Task 5 /15/88BACKGROUND: Create a new task of default size. Initialize it to execute the following code. Examples: This creates a task named spooler which lists the current file. STOP is needed at the end of a task. Assigns existing task named spooler to show screens 3 thru 15, and their shadows. The task named counter executes an infinite loop, so STOP is notrequired. Note that you MUST use PAUSE, or no other tasks will be executed. PAUSE is built in to all words which do I/O, so tasks which do I/O ( like spooler ) do not need to use PAUSE explicitly.