e18aaad637dc58bb59d3d94fb867bc84dbfe877f
[ghc-hetmet.git] / ghc / runtime / gum / SysMan.lc
1 %****************************************************************************
2 %
3 \section[Sysman.lc]{GUM Sysman Program}
4 %
5 %  (c) The Parade/AQUA Projects, Glasgow University, 1994-1995.
6 %      P. Trinder, November 30th. 1994.
7 %
8 %****************************************************************************
9
10 The Sysman task controls initiation, termination, global GC
11 synchronisation and statistics gathering. Based on K. Hammond's SysMan.lc
12 in Graph for PVM.
13
14 \begin{code}
15 #define NON_POSIX_SOURCE /* so says Solaris */
16
17 #include "rtsdefs.h"
18 #include "LLC.h"
19 \end{code}
20
21 \begin{code}
22 static GLOBAL_TASK_ID gtids[MAX_PES], IOTask =  0, StatsTask = 0;
23 static long PEbuffer[MAX_PES];
24 static int nPEs = 0;
25 \end{code}
26
27 \begin{code}
28 static GLOBAL_TASK_ID sysman_id, sender_id;
29
30 GLOBAL_TASK_ID mytid;
31
32 static unsigned PEsTerminated = 0;
33
34 static rtsBool Finishing = rtsFalse;
35 \end{code}
36
37 \begin{code}
38 #define checkerr(c)     do {if((c)<0) { pvm_perror("Sysman"); EXIT(EXIT_FAILURE); }} while(0)
39 \end{code}
40
41 This Function not yet implemented for GUM 
42
43 \begin{code}
44 static void
45 DoGlobalGC(STG_NO_ARGS)
46 {}
47 /*
48 static void
49 HandleException(STG_NO_ARGS)
50 {}
51 */
52 \end{code}
53
54 \begin{code}
55 main(int argc, char **argv)
56 {
57     int rbufid;
58     int opcode, nbytes;
59     char **pargv;
60     int i;
61 #if 0
62     int status;
63 #endif
64     int spawn_flag = PvmTaskDefault;
65
66     char *petask;
67
68     setbuf(stdout, NULL);
69     setbuf(stderr, NULL);
70
71     if (argc > 1) {
72         if (*argv[1] == '-') {
73             spawn_flag = PvmTaskDebug;
74             argv[1] = argv[0];
75             argv++; argc--;
76         }
77         sysman_id = pvm_mytid();/* This must be the first PVM call */
78         checkerr(sysman_id);
79
80         nPEs = atoi(argv[1]);
81
82         if ((petask = getenv(PETASK)) == NULL)
83             petask = PETASK;
84
85 #if 1
86         fprintf(stderr, "nPEs (%s) = %d\n", petask, nPEs);
87 #endif
88
89         /* Check that we can create the number of PE and IMU tasks requested */
90         if (nPEs > MAX_PES) {
91             fprintf(stderr, "No more than %d PEs allowed (%d requested)\n", MAX_PES, nPEs);
92             EXIT(EXIT_FAILURE);
93         }
94         /* Create the PE Tasks */
95         if (nPEs > 0) {
96             /* Initialise the PE task arguments from Sysman's arguments */
97             pargv = argv + 1;
98 #if 0
99             fprintf(stderr, "Spawning %d PEs(%s) ...\n", nPEs, petask);
100             fprintf(stderr, "  args: ");
101             for (i = 0; pargv[i]; ++i)
102                 fprintf(stderr, "%s, ", pargv[i]);
103             fprintf(stderr, "\n");
104 #endif
105
106             checkerr(pvm_spawn(petask, pargv, spawn_flag, "", nPEs, gtids));
107             for (i = 0; i < nPEs; i++)
108                 PEbuffer[i] = (long) gtids[i];
109 #if 0
110             fprintf(stderr, "Spawned /* PWT */\n");
111 #endif
112
113         }
114         /*
115            SysMan joins PECTLGROUP, so that it can wait (at the
116            barrier sysnchronisation a few instructions later) for the
117            other PE-tasks to start.
118            
119            Other comments on PVM groupery:
120            
121            The manager group (MGRGROUP) is vestigial at the moment. It
122            may eventually include a statistics manager, garbage
123            collector manager.
124
125            I suspect that you're [Kei Davis] right: Sysman shouldn't
126            be in PEGROUP, it's a hangover from GRIP.
127            
128            (Phil Trinder, 95/10)
129         */
130         checkerr(pvm_joingroup(PECTLGROUP));
131 #if 0
132         fprintf(stderr, "Joined PECTLGROUP /* PWT */\n");
133 #endif
134
135         /* Wait for all the PEs and IMUs to arrive */
136         checkerr(pvm_barrier(PECTLGROUP, nPEs + 1));
137
138 #if 0
139         fprintf(stderr, "PECTLGROUP  barrier passed /* HWL */\n");
140 #endif
141
142         /* Broadcast Global Task Ids of all PEs */
143
144         pvm_initsend(PvmDataDefault);
145         PutArgs(PEbuffer, nPEs);
146         pvm_bcast(PEGROUP, PP_PETIDS);
147
148 #if 0
149         /* Find an IO task */
150         for (i = 0; IOTask <= 0 || status != PvmOk; ++i) {
151             IOTask = pvm_gettid(PEGROUP, i);
152             status = pvm_pstat(IOTask);
153             fprintf(stderr, "Task %x, Status %x\n", IOTask, status);
154         }
155 #endif
156
157         IOTask = gtids[0];
158 #if 0
159         fprintf(stderr, "IO Task is [t%x]\n", IOTask);
160 #endif
161
162         pvm_initsend(PvmDataDefault);
163         pvm_send(IOTask, PP_IO_INIT);
164
165         pvm_initsend(PvmDataDefault);
166         pvm_bcast(PEGROUP, PP_INIT);
167 #if 0
168         fprintf(stderr, "Broadcast PP_INIT to all PEs\n");
169 #endif
170
171         /* HWL-DEBUG */
172 #if 0
173         fprintf(stderr, "Sysman successfully initialized!\n");
174 #endif
175
176         /* Process incoming messages */
177         while (1) {
178             if ((rbufid = pvm_recv(ANY_TASK, ANY_OPCODE)) < 0)
179                 pvm_perror("Sysman: Receiving Message");
180
181             else {
182                 pvm_bufinfo(rbufid, &nbytes, &opcode, &sender_id);
183
184 #if 0
185                 fprintf(stderr, "HWL-DBG(SysMan; main loop): rbufid=%x, nbytes = %d, opcode = %x, sender_id = %x\n",
186                   rbufid, nbytes, opcode, sender_id);
187 #endif
188
189                 switch (opcode) {
190                 case PP_GC_INIT:
191                     /* This Function not yet implemented for GUM */
192                     fprintf(stderr, "Global GC from %x Not yet implemented for GUM!\n", sender_id);
193                     sync(PECTLGROUP, PP_FULL_SYSTEM);
194                     broadcast(PEGROUP, PP_GC_INIT);
195                     DoGlobalGC();
196                     broadcast(PEGROUP, PP_INIT);
197                     break;
198
199                 case PP_STATS_ON:
200                 case PP_STATS_OFF:
201                     /* This Function not yet implemented for GUM */
202                     break;
203
204                 case PP_FINISH:
205                     fprintf(stderr, "Finish from %x\n", sender_id);
206                     if (!Finishing) {
207                         long buf = (long) StatsTask;
208                         Finishing = rtsTrue;
209                         pvm_initsend(PvmDataDefault);
210                         pvm_pklong(&buf, 1, 1);
211                         pvm_bcast(PEGROUP, PP_FINISH);
212                     } else {
213                         ++PEsTerminated;
214                     }
215
216                     if (PEsTerminated >= nPEs) {
217                         broadcast(PEGROUP, PP_FINISH);
218                         broadcast(MGRGROUP, PP_FINISH);
219                         pvm_lvgroup(PEGROUP);
220                         pvm_lvgroup(PECTLGROUP);
221                         pvm_lvgroup(MGRGROUP);
222                         pvm_exit();
223                         EXIT(EXIT_SUCCESS);
224                     }
225                     break;
226
227                 case PP_FAIL:
228                     fprintf(stderr, "Fail from %x\n", sender_id);
229                     if (!Finishing) {
230                         Finishing = rtsTrue;
231                         broadcast(PEGROUP, PP_FAIL);
232                     }
233                     break;
234
235                 default:
236                     {
237 /*                    char *opname = GetOpName(opcode);
238                       fprintf(stderr,"Sysman: Unrecognised opcode %s (%x)\n",
239                                      opname,opcode);    */
240                         fprintf(stderr, "Sysman: Unrecognised opcode (%x)\n",
241                           opcode);
242                     }
243                     break;
244                 }
245             }
246         }
247     }
248     return(0);
249 }
250 \end{code}
251
252 @myexit@ for the system manager.
253
254 \begin{code}
255
256 void
257 myexit(n)
258 I_ n;
259 {
260 #ifdef exit
261 #undef exit
262 #endif
263     exit(n);
264 }
265
266 \end{code}