home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1996-02-01 | 4.9 KB | 100 lines |
- Syntax10.Scn.Fnt
- Syntax10b.Scn.Fnt
- Syntax10i.Scn.Fnt
- MODULE Coroutines; (* jr/14jul94, updated cn/20jan96 *)
- This module implements coroutines as known from Modula-2. Although it is machine
- dependent, it was programed in a way, which should make it adaptable to
- differen platforms by just a few changes in constant definitions. See the section marked CHANGE.
- There is one restriction which procedures, that you use to create processe in NEWPROCESS,
- have to obey. If they allocate space on the heap they must assure, that some global variable
- points to this space during the entiere time this space is needed. If you don't follow this rule,
- the garbage collector may reclaim the space, even though you still have some local
- variables pointing to it.
- On the Macintosh there is an additional restriction. The storage are used as stack for
- a process has itself to be on the stack. Otherwise some check code will complain
- about illegal stack pointer values.
- This module was used on the different platforms at different stages of its development.
- It showed some strange efects on the Oberon system, which we suspected as
- a problem with garbage collection. I've fixed it now for the SGI Oberon. As I don't have
- access to the other platforms, I don't really know if this module is still usable on them.
- In theory, this is expected:
- Macintosh:
- The Mac Oberon does never perform garbage collection while outside of the
- Oberon.Loop and therefore does not have to inspect the stack when deciding
- which memory space is to be marked as in use. Thus the disabling of the garbage
- collector is not needed, and the statements using Kernel.GCenabled can be
- removed, maybe even have to be removed, as Kernel doesn't export GCenabled.
- SGI,HP:
- The garbage collector may be called when executing a command. It then scans
- the stack to see, if there are pointer pointing to some heap ares, so it can mark
- this area as in use. When executing a process, the stack pointer points to the
- private stack of this process, and no more to the usual one. And if it points to the
- wrong side of the stack, the garbage collector will not inspect the stack at all.
- Therefore we disable the garbage collector when we are not in the main
- execution thread, and reenable it, when we return to the main thread.
- In case your command traps, while executing a coroutine, the garbage collector
- remains disabled, and Coroutines continues to believe, that you are not in the
- main thread. You should then use the Coroutines.Reset command to reenable the
- garbage collector, and reset Coroutines.
- Amiga:
- The same as said for SGI and HP applies to the Amiga. But I don't know, if the
- Amiga Kernel does export an GCenabled variable, as the Unix Kernel does.
- If it doesn't, you have to wait for a future relase supporting it.
- Later it was discovered, that the problem was cause by writing to the Log, while
- executing code called from the handler in the SortBasic module.
- Apart from the above mentioned problems, their might be others. So please be
- carefull when using commands which use Coroutines. Don't do this, while you
- have viewers with unsaved files open etc.
- If you can identify problems with Coroutines, please send Mail to
- claudio@dial.eunet.ch or joerg.straube@alcatel.ch
- so we can improve this module.
- The modifications for AXP were provided by
- Guenter Dotzel <100023.2527@compuserve.com>
- Thank you very much!
- IMPORT SYSTEM,Kernel;
- CONST (* CHANGE *)
- (* Amiga/Mac: *) MP=14; SP=15; negativeGrow=TRUE; align=4;
- (* HP: MP=30; SP=30; negativeGrow=FALSE; align=4; *)
- (* SGI: MP=29; SP=29; negativeGrow=TRUE; align=4; *)
- (* AXP: MP=29; SP=30; negativeGrow=TRUE; align=16; TYPE LONGINT=SYSTEM.SIGNED_64; *)
- PROC*=PROCEDURE;
- PROCESS*=RECORD
- p:PROC;
- stackForP:LONGINT;
- MP:LONGINT
- END;
- mainMP:LONGINT;
- proc:PROC;
- PROCEDURE NEWPROCESS*(p:PROC; VAR stack:ARRAY OF SYSTEM.BYTE; VAR new:PROCESS);
- BEGIN
- new.p:=p;
- IF negativeGrow THEN
- new.stackForP:=((SYSTEM.ADR(stack)+LEN(stack)) DIV align)*align; (* respect alignment requirments *)
- ELSE
- new.stackForP:=((SYSTEM.ADR(stack)+3) DIV align)*align; (* long word align *)
- END;
- new.MP:=0;
- END NEWPROCESS;
- PROCEDURE TRANSFER*(VAR from,to:PROCESS);
- BEGIN
- SYSTEM.GETREG(MP,from.MP);
- IF mainMP=0 THEN Kernel.GCenabled:=FALSE; mainMP:=from.MP; END;
- IF to.MP#0 THEN
- SYSTEM.PUTREG(MP,to.MP)
- ELSE
- proc:=to.p; (* copy into global variable needed when MP=SP *)
- SYSTEM.PUTREG(SP,to.stackForP);
- IF to.MP=mainMP THEN Kernel.GCenabled:=TRUE; mainMP:=0; END;
- proc;
- HALT(100);
- END;
- END TRANSFER;
- PROCEDURE Reset*;
- BEGIN
- mainMP:=0;
- Kernel.GCenabled:=TRUE;
- END Reset;
- BEGIN
- Reset;
- END Coroutines.
-