[9] | 1 | /*
|
---|
| 2 | (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
---|
| 3 | See the copyright notice in the ACK home directory, in the file "Copyright".
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
| 7 | Module: SYSTEM
|
---|
| 8 | Author: Ceriel J.H. Jacobs
|
---|
| 9 | Version: $Header: /cvsup/minix/src/lib/ack/libm2/SYSTEM.c,v 1.1 2005/10/10 15:27:46 beng Exp $
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | /*
|
---|
| 13 | An implementation of the Modula-2 NEWPROCESS and TRANSFER facilities
|
---|
| 14 | using the topsize, topsave, and topload facilities.
|
---|
| 15 | For each coroutine, a proc structure is built. For the main routine,
|
---|
| 16 | a static space is declared to save its stack. For the other coroutines,
|
---|
| 17 | the user specifies this space.
|
---|
| 18 | */
|
---|
| 19 |
|
---|
| 20 | #include <m2_traps.h>
|
---|
| 21 |
|
---|
| 22 | #define MAXMAIN 2048
|
---|
| 23 |
|
---|
| 24 | struct proc {
|
---|
| 25 | unsigned size; /* size of saved stackframe(s) */
|
---|
| 26 | int (*proc)(); /* address of coroutine procedure */
|
---|
| 27 | char *brk; /* stack break of this coroutine */
|
---|
| 28 | };
|
---|
| 29 |
|
---|
| 30 | extern unsigned topsize();
|
---|
| 31 |
|
---|
| 32 | static struct proc mainproc[MAXMAIN/sizeof(struct proc) + 1];
|
---|
| 33 |
|
---|
| 34 | static struct proc *curproc = 0;/* current coroutine */
|
---|
| 35 | extern char *MainLB; /* stack break of main routine */
|
---|
| 36 |
|
---|
| 37 | _SYSTEM__NEWPROCESS(p, a, n, p1)
|
---|
| 38 | int (*p)(); /* coroutine procedure */
|
---|
| 39 | struct proc *a; /* pointer to area for saved stack-frame */
|
---|
| 40 | unsigned n; /* size of this area */
|
---|
| 41 | struct proc **p1; /* where to leave coroutine descriptor,
|
---|
| 42 | in this implementation the address of
|
---|
| 43 | the area for saved stack-frame(s) */
|
---|
| 44 | {
|
---|
| 45 | /* This procedure creates a new coroutine, but does not
|
---|
| 46 | transfer control to it. The routine "topsize" will compute the
|
---|
| 47 | stack break, which will be the local base of this routine.
|
---|
| 48 | Notice that we can do this because we do not need the stack
|
---|
| 49 | above this point for this coroutine. In Modula-2, coroutines
|
---|
| 50 | must be level 0 procedures without parameters.
|
---|
| 51 | */
|
---|
| 52 | char *brk = 0;
|
---|
| 53 | unsigned sz = topsize(&brk);
|
---|
| 54 |
|
---|
| 55 | if (sz + sizeof(struct proc) > n) {
|
---|
| 56 | /* not enough space */
|
---|
| 57 | TRP(M2_TOOLARGE);
|
---|
| 58 | }
|
---|
| 59 | a->size = n;
|
---|
| 60 | a->proc = p;
|
---|
| 61 | a->brk = brk;
|
---|
| 62 | *p1 = a;
|
---|
| 63 | if (topsave(brk, a+1))
|
---|
| 64 | /* stack frame saved; now just return */
|
---|
| 65 | ;
|
---|
| 66 | else {
|
---|
| 67 | /* We get here through the first transfer to the coroutine
|
---|
| 68 | created above.
|
---|
| 69 | This also means that curproc is now set to this coroutine.
|
---|
| 70 | We cannot trust the parameters anymore.
|
---|
| 71 | Just call the coroutine procedure.
|
---|
| 72 | */
|
---|
| 73 | (*(curproc->proc))();
|
---|
| 74 | _cleanup();
|
---|
| 75 | _exit(0);
|
---|
| 76 | }
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | _SYSTEM__TRANSFER(a, b)
|
---|
| 80 | struct proc **a, **b;
|
---|
| 81 | {
|
---|
| 82 | /* transfer from one coroutine to another, saving the current
|
---|
| 83 | descriptor in the space indicated by "a", and transfering to
|
---|
| 84 | the coroutine in descriptor "b".
|
---|
| 85 | */
|
---|
| 86 | unsigned size;
|
---|
| 87 |
|
---|
| 88 | if (! curproc) {
|
---|
| 89 | /* the current coroutine is the main process;
|
---|
| 90 | initialize a coroutine descriptor for it ...
|
---|
| 91 | */
|
---|
| 92 | mainproc[0].brk = MainLB;
|
---|
| 93 | mainproc[0].size = sizeof(mainproc);
|
---|
| 94 | curproc = &mainproc[0];
|
---|
| 95 | }
|
---|
| 96 | *a = curproc; /* save current descriptor in "a" */
|
---|
| 97 | if (*b == curproc) {
|
---|
| 98 | /* transfer to itself is a no-op */
|
---|
| 99 | return;
|
---|
| 100 | }
|
---|
| 101 | size = topsize(&(curproc->brk));
|
---|
| 102 | if (size + sizeof(struct proc) > curproc->size) {
|
---|
| 103 | TRP(M2_TOOLARGE);
|
---|
| 104 | }
|
---|
| 105 | if (topsave(curproc->brk, curproc+1)) {
|
---|
| 106 | /* stack top saved. Now restore context of target
|
---|
| 107 | coroutine
|
---|
| 108 | */
|
---|
| 109 | curproc = *b;
|
---|
| 110 | topload(curproc+1);
|
---|
| 111 | /* we never get here ... */
|
---|
| 112 | }
|
---|
| 113 | /* but we do get here, when a transfer is done to the coroutine in "a".
|
---|
| 114 | */
|
---|
| 115 | }
|
---|