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 | }
|
---|