| \ Multitasker 19aug94py |
\ Multitasker 19aug94py |
| |
|
| \ Copyright (C) 1995-1997 Free Software Foundation, Inc. |
\ Copyright (C) 1995,1996,1997,2001,2003,2007 Free Software Foundation, Inc. |
| |
|
| \ This file is part of Gforth. |
\ This file is part of Gforth. |
| |
|
| \ Gforth is free software; you can redistribute it and/or |
\ Gforth is free software; you can redistribute it and/or |
| \ modify it under the terms of the GNU General Public License |
\ modify it under the terms of the GNU General Public License |
| \ as published by the Free Software Foundation; either version 2 |
\ as published by the Free Software Foundation, either version 3 |
| \ of the License, or (at your option) any later version. |
\ of the License, or (at your option) any later version. |
| |
|
| \ This program is distributed in the hope that it will be useful, |
\ This program is distributed in the hope that it will be useful, |
| \ GNU General Public License for more details. |
\ GNU General Public License for more details. |
| |
|
| \ You should have received a copy of the GNU General Public License |
\ You should have received a copy of the GNU General Public License |
| \ along with this program; if not, write to the Free Software |
\ along with this program. If not, see http://www.gnu.org/licenses/. |
| \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
| |
|
| Create sleepers sleepers A, sleepers A, 0 , |
Create sleepers sleepers A, sleepers A, 0 , |
| |
|
| \ LINK-TASK links task1 into the task chain of task2 |
|
| : link-task ( task1 task2 -- ) |
: link-task ( task1 task2 -- ) |
| |
\G LINK-TASK links task1 into the task chain of task2 |
| over 2@ 2dup cell+ ! swap ! \ unlink task1 |
over 2@ 2dup cell+ ! swap ! \ unlink task1 |
| 2dup @ cell+ ! 2dup dup @ rot 2! ! ; |
2dup @ cell+ ! 2dup dup @ rot 2! ! ; |
| |
|
| : sleep ( task -- ) sleepers link-task ; |
: sleep ( task -- ) |
| : wake ( task -- ) next-task link-task ; |
\G deactivates task |
| |
sleepers link-task ; |
| |
: wake ( task -- ) |
| |
\G activates task |
| |
next-task link-task ; |
| |
|
| \ PAUSE is the task-switcher |
|
| : pause ( -- ) |
: pause ( -- ) |
| |
\G PAUSE is the task-switcher |
| rp@ fp@ lp@ sp@ save-task ! |
rp@ fp@ lp@ sp@ save-task ! |
| next-task @ up! save-task @ sp! |
next-task @ up! save-task @ sp! |
| lp! fp! rp! ; |
lp! fp! rp! ; |
| |
|
| \ STOP sleeps a task and switches to the next |
|
| : stop ( -- ) |
: stop ( -- ) |
| |
\G STOP sleeps a task and switches to the next |
| rp@ fp@ lp@ sp@ save-task ! |
rp@ fp@ lp@ sp@ save-task ! |
| next-task @ up! save-task @ sp! |
next-task @ up! save-task @ sp! |
| lp! fp! rp! prev-task @ sleep ; |
lp! fp! rp! prev-task @ sleep ; |
| |
|
| \ USER' computes the task offset |
:noname ' >body @ ; |
| : user' ( 'user' -- n ) |
:noname ' >body @ postpone literal ; |
| ' >body @ postpone literal ; immediate |
interpret/compile: user' ( 'user' -- n ) |
| interpretation: |
\G USER' computes the task offset of a user variable |
| ' >body @ ; |
|
| |
|
| \ NEWTASK creates a new, sleeping task |
: NewTask ( stacksize -- Task ) dup 2* 2* udp @ + dup |
| : NewTask ( n -- Task ) dup 2* 2* udp @ + dup |
\G NEWTASK creates a new, sleeping task |
| allocate throw + >r |
allocate throw + >r |
| r@ over - udp @ - next-task over udp @ move |
r@ over - udp @ - next-task over udp @ move |
| r> over user' rp0 + ! dup >r |
r> over user' rp0 + ! dup >r |
| dup r@ user' fp0 + ! over - |
dup r@ user' fp0 + ! over - |
| dup r@ user' sp0 + ! over - |
dup r@ user' sp0 + ! over - |
| dup r@ user' normal-dp + dup >r ! |
dup r@ user' normal-dp + dup >r ! |
| r> r@ user' dpp + ! + $10 + |
r> r@ user' dpp + ! 2drop |
| r@ user' >tib + ! |
0 r@ user' current-input + ! |
| r> dup 2dup 2! dup sleep ; |
r> dup 2dup 2! dup sleep ; |
| |
|
| : kill-task |
Create killer killer A, killer A, |
| |
: kill ( task -- ) |
| |
\G kills a task - deactivate and free task area |
| |
dup killer link-task killer dup dup 2! |
| |
user' normal-dp + @ free throw ; |
| |
|
| |
: kill-task ( -- ) |
| |
\G kills the current task, also on bottom of return stack of a new task |
| next-task @ up! save-task @ sp! |
next-task @ up! save-task @ sp! |
| lp! fp! rp! prev-task @ dup dup link-task user' normal-dp + @ free throw ; |
lp! fp! rp! prev-task @ kill ; |
| |
|
| : (pass) ( x1 .. xn n task -- ) rdrop |
: (pass) ( x1 .. xn n task -- ) rdrop |
| [ ' kill-task >body ] ALiteral r> |
[ ' kill-task >body ] ALiteral r> |
| cells r@ user' sp0 + @ tuck swap - dup r@ user' save-task + ! |
cells r@ user' sp0 + @ tuck swap - dup r@ user' save-task + ! |
| ?DO I ! cell +LOOP r> wake ; |
?DO I ! cell +LOOP r> wake ; |
| |
|
| : activate ( task -- ) 0 swap (pass) ; |
: activate ( task -- ) |
| : pass ( x1 .. xn n task -- ) (pass) ; |
\G activates the task. |
| |
\G Continues execution with the caller of ACTIVATE. |
| |
0 swap (pass) ; |
| |
: pass ( x1 .. xn n task -- ) |
| |
\G passes n parameters to the task and activates that task. |
| |
\G Continues execution with the caller of PASS. |
| |
(pass) ; |
| |
|
| : single-tasking? ( -- flag ) |
: single-tasking? ( -- flag ) |
| |
\G checks if only one task is running |
| next-task dup @ = ; |
next-task dup @ = ; |
| |
|
| : task-key BEGIN pause key? single-tasking? or UNTIL (key) ; |
: task-key BEGIN pause key? single-tasking? or UNTIL (key) ; |