source: trunk/minix/lib/ack/libm2/SYSTEM.c@ 12

Last change on this file since 12 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 3.1 KB
RevLine 
[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
24struct 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
30extern unsigned topsize();
31
32static struct proc mainproc[MAXMAIN/sizeof(struct proc) + 1];
33
34static struct proc *curproc = 0;/* current coroutine */
35extern 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}
Note: See TracBrowser for help on using the repository browser.