home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
pd6.lzh
/
LIB
/
TILE
/
multi_tasking.f83
< prev
next >
Wrap
Text File
|
1989-12-23
|
11KB
|
269 lines
\
\ MULTI-TASKING DEFINITIONS
\
\ Copyright (c) 1989 by Mikael R.K. Patel
\
\ Computer Aided Design Laboratory (CADLAB)
\ Department of Computer and Information Science
\ Linkoping University
\ S-581 83 LINKOPING
\ SWEDEN
\
\ Email: mip@ida.liu.se
\
\ Started on: 30 June 1988
\
\ Last updated on: 6 December 1989
\
\ Dependencies:
\ (forth) enumerates, structures, queues
\
\ Description:
\ Allows definition of tasks, semaphores and channels. Follows the
\ basic models of concurrent programming primitives.
\
\ Copying:
\ This program is free software; you can redistribute it and\or modify
\ it under the terms of the GNU General Public License as published by
\ the Free Software Foundation; either version 1, or (at your option)
\ any later version.
\
\ This program is distributed in the hope that it will be useful,
\ but WITHOUT ANY WARRANTY; without even the implied warranty of
\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\ GNU General Public License for more details.
\
\ You should have received a copy of the GNU General Public License
\ along with this program; see the file COPYING. If not, write to
\ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
.( Loading Multi-tasking definitions...) cr
#include enumerates.f83
#include structures.f83
#include queues.f83
queues structures multi-tasking definitions
( Task structure and status codes)
struct.type TASK ( -- )
struct QUEUE +queue private ( System administration of tasks)
enum +status private ( Status code field)
ptr +sp private ( Parameter stack pointer)
ptr +s0 private ( Parameter stack bottom pointer)
ptr +ip private ( Instruction pointer)
ptr +rp private ( Return stack pointer)
ptr +r0 private ( Return stack bottom pointer)
ptr +fp private ( Argument frame stack pointer)
ptr +ep private ( Exception frame pointer)
struct.end
enumerates
enum.type TASK-STATUS-CODES
enum TERMINATED ( Terminated status code)
enum READY ( Ready for "schedule")
enum RUNNING ( Scheduled and running)
enum IOWAITING ( Waiting for in- or output)
enum WAITING ( Generic waiting)
enum DELAYED ( In delay function call)
enum.end
multi-tasking
( Task inquiry and manipulation functions)
: deactivate ( queue task -- )
running @ succ >r ( Access the next runnable task)
dup out ( Remove this task from the queue)
swap into ( And insert into queue of waiting)
r> resume ; ( The next task)
: activate ( task -- )
running @ succ into ( And insert it after the current task)
detach ; ( And restart it)
: delay ( n -- )
DELAYED running @ +status ! ( Indicate that the task is delayed)
0 do detach loop ( Delay a task a number of switches)
RUNNING running @ +status ! ; ( Restore running state)
: join ( task -- )
WAITING running @ +status ! ( Indicate that the task is waiting)
begin ( Wait for task to terminate)
dup +status @ ( Check status. While not zero)
while ( and thus not terminate)
detach ( Switch tasks)
repeat drop ( Drop task parameter)
RUNNING running @ +status ! ; ( Restore running state)
: who ( -- )
." task#(s): " ( Print header and list of tasks)
running @ print cr ; ( addresses)
( Dijkstra's Semaphore definition)
struct.type SEMAPHORE ( n -- )
struct QUEUE +waiting private ( Queue of waiting tasks)
long +count private ( Current counter value)
struct.init ( n semaphore -- )
dup +waiting as QUEUE initiate ( Initiate semephore queue)
+count ! ( Initiate semaphore counter)
struct.end
: mutex ( -- )
1 SEMAPHORE ; ( Mutual exclusion semaphore)
: signal ( semaphore -- )
dup +waiting ?empty ( Check if the waiting queue is empty)
if 1 swap +count +! ( Increment counter)
else
+waiting succ dup out ( Remove the first waiting task)
activate ( And reactivate the task)
then ;
: ?wait ( semaphore -- flag)
+count @ 0= ; ( Check if a wait will delay the task)
: wait ( semaphore -- )
dup ?wait ( Does the task have to wait)
if WAITING running @ +status ! ( Indicate that the task is waiting)
+waiting running @ deactivate ( Deactivate to the waiting queue)
RUNNING running @ +status ! ( Restore running state)
else
-1 swap +count +! ( Decrement the counter)
then ;
( Extension of Hoare's Channels)
enum.type COMMUNICATION-MODES
enum ONE-TO-ONE ( Task to task communication)
enum ONE-TO-MANY ( One task to several tasks)
enum MANY-TO-ONE ( Serveral task to one task)
enum.end
struct.type CHAN ( mode -- )
long +data private ( Data past from sender to receiver)
long +mode private ( Communication mode)
struct SEMAPHORE +sent private ( Semaphore for sender)
struct SEMAPHORE +received private ( Semaphore for receiver)
struct.init ( mode chan -- )
swap over +mode ! ( Set up channel mode)
0 over +sent as SEMAPHORE initiate ( Initiate semaphore fields)
0 swap +received as SEMAPHORE initiate ( as synchronize semphores)
struct.end
: ?avail ( chan -- flag)
dup +mode @ MANY-TO-ONE = ( Check channel mode)
if +received ?wait not ( Check if receiver is available)
else +sent ?wait not then ; ( Check if sender is available)
: send ( data chan -- )
dup +mode @ MANY-TO-ONE = ( Check mode first)
if dup +received wait ( Wait for a receiver)
swap over +data ! ( Assign data field)
+sent signal ( And signal the receiver)
else
swap over +data ! ( Assign data field of channel)
dup +sent signal ( Signal that data is available)
+received wait ( And wait for receiver to fetch)
then ;
: receive ( chan -- data)
dup +mode @ MANY-TO-ONE = ( Check mode first)
if dup +received signal ( Signal a receiver is ready)
dup +sent wait ( Wait for sender)
+data @ ( Fetch sent data from channel)
else
dup +sent wait ( Wait for sender to send data)
dup +data @ ( Fetch data from channel)
swap +received signal ( And acknowledge to sender)
then ;
( Message passing; rendezvous)
struct.type RENDEZVOUS ( -- )
struct CHAN +arg private ( Channel for argument sending)
struct CHAN +res private ( Channel for result receiving)
struct.init ( rendezvous -- )
ONE-TO-ONE over +arg as CHAN initiate ( Initiate argument channel)
ONE-TO-ONE swap +res as CHAN initiate ( Initiate result channel)
struct.does ( arg rendezvous -- res)
swap over +arg send ( Send the argument)
+res receive ( and receive the result)
struct.end
: accept ( -- rendezvous arg)
' >body [compile] literal ( Access the rendezvous structure)
?compile dup ( Receive the argument to this task)
?compile +arg
?compile receive ; immediate
: accept.end ( rendezvous res -- )
?compile swap ( Send the result to the sender)
?compile +res
?compile send ; immediate
: ?awaiting ( -- boolean)
' >body [compile] literal ( Access the rendezvous structure)
?compile +arg ( Check if an argument is available)
?compile ?avail ; immediate
( High Level Task definition with user variables)
forward make ( task.type -- task)
struct.type task.type ( parameters returns -- )
long +users private ( Size of user area in bytes)
long +parameters private ( Size of parameter stack)
long +returns private ( Size of return stack)
ptr +body private ( Pointer to task body code)
struct.init ( parameters returns task.type -- task.type users0)
dup >r +returns ! ( Assign given fields)
r@ +parameters ! ( And prepare for definition of)
r> sizeof TASK ( user variable fields for tasks)
struct.does ( task -- )
make dup schedule constant ( Make a task, start it)
struct.end ( And give it a name)
: make ( task.type -- task)
dup >r +users @ ( Fetch task size parameters)
r@ +parameters @ ( And pointer to task body)
r@ +returns @ ( And create a task instance)
r> +body @ task ;
: new ( -- task)
' >body [compile] literal ( Requires symbol after to be a task)
?compile make ( type. Makes a task instance and)
?compile dup ( schedules it. Return pointer to)
?compile schedule ; immediate ( create instance)
: bytes ( users1 size -- users2)
over user + ; ( Create a user variable and update)
: field ( size -- )
create , ( Save size of user variable type)
does> @ bytes ; private ( Fetch size and create field name)
: struct ( -- )
[compile] sizeof bytes ; ( Fetch size of structure and create)
1 field byte ( -- )
2 field word ( -- )
4 field long ( -- )
4 field ptr ( -- )
4 field enum ( -- )
: task.body ( task.type users3 -- )
align over +users ! ( Align and assign user area size)
here swap +body ! ( Assign pointer to task body code)
] ; ( And start compiling)
: task.end ( -- )
[compile] ; ; immediate compilation ( Stop compiling)
forth only