\ AKernel.blk 23Sep88pJa A4th A Public Domain Forth system for Amiga's based on Laxen & Perry's F83 This Forth system is Public Domain. You may freely distribute copy and use it, for any legal purposes. I cannot be held responsible for any errors and/or omissions, I do not warrant this system. I bear no responsibility for any use or abuse, with or without intend. Peter J. Appelman. \ Load screen 01Oct88pJadecimal only forth also definitions 3 load only forth Exec also forth Intuition also forth also definitions vocabulary tasks tasks definitions 3 7 +thru only forth also definitions cr .( Task support loaded ) \ (spare) 01Oct88pJa \ Load include files. 01Oct88pJaonly forth also Exec definitions tload i:exec/memory tload i:exec/nodes tload i:exec/tasks \ default values 01Oct88pJavariable stacksize 2048 stacksize ! variable rstacksize 512 rstacksize ! variable taskpriority -25 taskpriority ! variable remember 0 remember ! variable minsize #users 4* 44 + 128 + 256 + minsize ! : returnstack (s -- flags size ) MEMF_CLEAR rstacksize @ ; : stack (s -- flags size ) MEMF_CLEAR stacksize @ ; : task (s -- flags size ) MEMF_CLEAR MEMF_PUBLIC or [ sizeoff Task ] literal ; : getit (s flags size -- addr ) remember -rot AllocRemember ; \ making a task image. 01Oct88pJa: ok? (s addr -- ) 0= if ." No memory for task" remember FreeRemember abort then ; forth definitions : task: \ name (s -- ) [ tasks ] remember off >in @ bl astring swap >in ! create task getit dup ok? , , ( name ) taskpriority @ , stack getit ok? returnstack getit ok? remember @ , here mem-link @ , mem-link ! @next #users 4* - here #users 4* 44 + move minsize @ allot ; tasks definitions \ stopping a task, setting priority. 01Oct88pJa: running? (s 'task -- f ) @ { Task tc_State s@ dup 0= swap 6 = or not ; : stoptask (s 'task -- ) dup running? if @ RemTask else drop then ; forth definitions : stop (s -- ) 0 RemTask ; : priority (s 'task pr -- oldpr ) [ tasks ] swap dup running? if @ swap SetTaskPri else 8+ dup @ -rot ! then ; tasks definitions \ assigning a task to some code and starting it. 01Oct88pJa: sp>sp (s .. n tsp -- 'tsp ) swap dup >r 0 ?do 4- tuck ! loop 4- r> over ! ; : set-task (s #par 'task ip -- ) over stoptask swap dup @ dup >r [ sizeoff Task ] literal erase 4+ dup @ r@ { Node ln_Name s! 4+ dup @ r@ ln_Pri s! NT_TASK r@ ln_Type s! 4+ dup @ @ dup 4+ @ swap 8+ @ dup r@ { Task tc_SPLower s! + dup r@ tc_SPUpper s! 4- tuck ! (s ... n ip 'tsp ) swap >r sp>sp 4- r> over ! r@ tc_SPReg s! 0 ['] tinit r> AddTask ; \ activating a task. 01Oct88pJaforth definitions : activate (s ... n task -- ) [ tasks ] r> set-task ; \ Tasks.blk 01Oct88pJaTasks for A4th Round robin task handlers are a waste of time on the Amiga. Execsets the tone for multitasking. Efficiency is not in question. Tasks here are concidered background to the forth system. Priority is set low, allowing responsive keyboard. (Priority is controlable). Tasks have their own stacks and small dictionary area, the last for number I/O and 'pad' *only*!! Tasks can expect parameters, to use as they like. No return parameters. Control between tasks and resources is up to you, using semaphores, signals, etc. \ task image 01Oct88pJaThe dictionary entry for a task is as follows: ( min 600 bytes )a"name <name> header <name> cfa docreate pfa @task (points to task structure) @name (points to a"name ) priority (priority number ) remember key (list of memory allocated) mem-link user area ..... (>next) next ..... (dp) dictionary ..... \ remember list. 01Oct88pJaThe remember key is the start of the list of memory allocated for the local task. It is as follows: remem.key ---> link ---> link ---> 0 rp.size sp.size tsk.size rp.addr sp.addr tsk.addr The last entry is the task structure itself. It is also recorded in the task word itself. The stack addresses, upper, and lower regs must be set in the task structure, before AddTask is called. Parameters must be copied. The return stack pointer is set up by the task init routine. \ The task local stack at startup. 01Oct88pJaThe task's stack before the init routine starts looks as follows SP.Upper --> addr.of rememberkey parameters ...... param.count ip SP.Reg ---> default.return (put there by Exec) .... .... SP.Lower --> .... The default.return routine must be put at the addr.of.rememkey and that one is used to set rp. ip is popped of the stack together with the param.count. Addr.of.rememkey is used to set >next=a3 and dp. \ default values 01Oct88pJastacksize These are default sizes and can be changed before rstacksize ..the task is created. Remember is used to record taskpriority ..until it can be saved in the task image. remember ..minsize is the minimum dictionary each task willminsize ..use from the forth system. returnstack (s -- flags size ) return the size and flags, ready for a call to AllocRemember stack (s -- flags size ) Regular stack. task (s -- flags size ) The task structure. getit (s flags size -- addr ) Allocate the memory, returns null if not possible. \ making a task image. 01Oct88pJaok? (s addr -- ) \ check addr for null. Checks for a null address and aborts, releasing previously allocated memory. task: \ name (s -- ) create a task not initialized. Creates a task image in the dictionary, allocates stacks and structures. Does not initialize any of it. The remember pointer is saved with a link to mem-link right after it; forgetting is no problem. Last two lines copy task (user) variable area and a copy of next and rcall routine. (It is not nice to create a task while debugging :-) \ stopping a task, setting priority. 06Sep88pJarunning? (s 'task -- f ) Checks the task State and returns true if it in use. 0 is a new task 6 is removed. stoptask (s 'task -- ) Stops a task, by calling RemTask. This can be trouble. Any allocations of system resources would not be returned. It is better to stop the task from within it. stop (s -- ) remove one selve. priority (s 'task pr -- oldpr ) sets priority of the task, whether it is running or not. Returns the oldpriority. \ assigning a task to some code and starting it. 01Oct88pJasp>sp (s .. n tsp -- 'tsp ) copy n number of parameters moves param to the task stack, pointer is on the stack. set-task (s #par 'task ip -- ) Initializes the task. This is a minimal task setup. The name priority and type are setup in the Node. Next the stack is calculated. The parameters are copied and the registers are setup. AddTask will start the task immediately. \ activating a task. 01Oct88pJaactivate (s ... n task -- ) points a task to the next code and starts it. Usage: task: counter \ create a task variable cnts \ : docount (s n -- ) 1 counter activate \ expects one parameter, here the 0 ?do 1 cnts +! loop stop ; \ loop end. 50000 docount \ start background counter to 50000