1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include <dx/dx.h>
11
12 #if defined(DDX)
13 #if defined(DXD_EXEC_WAIT_PROCESS)
14 #undef DXD_EXEC_WAIT_PROCESS
15 #endif
16 #define DXD_EXEC_WAIT_PROCESS 0
17 #define DXD_MASTER_IS_P0 1
18 #endif
19
20 #if defined(HAVE_WINIOCTL_H)
21 #include <winioctl.h>
22 #endif
23 #if defined(HAVE_SYS_IOCTL_H)
24 #include <sys/ioctl.h>
25 #endif
26 #if defined(HAVE_SYS_TYPES_H)
27 #include <sys/types.h>
28 #endif
29 #if defined(HAVE_SYS_TIMES_H)
30 #include <sys/times.h>
31 #endif
32 #if defined(HAVE_SYS_PARAM_H)
33 #include <sys/param.h>
34 #endif
35 #if defined(HAVE_SYS_TIMEB_H)
36 #include <sys/timeb.h>
37 #endif
38 #if defined(HAVE_SYS_TIME_H)
39 #include <sys/time.h>
40 #endif
41 #if defined(HAVE_TIME_H)
42 #include <time.h>
43 #endif
44 #if defined(HAVE_SYS_SIGNAL_H)
45 #include <sys/signal.h>
46 #endif
47 #if defined(HAVE_CTYPE_H)
48 #include <ctype.h>
49 #endif
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <stdarg.h>
54
55 #if defined(HAVE_UNISTD_H)
56 #include <unistd.h>
57 #endif
58 #if defined(HAVE_CONIO_H)
59 #include <conio.h>
60 #endif
61 #if defined(HAVE_ERRNO_H)
62 #include <errno.h>
63 #endif
64 #if defined(HAVE_NETDB_H)
65 #include <netdb.h>
66 #endif
67 #if defined(HAVE_SYS_FILIO_H)
68 #include <sys/filio.h>
69 #endif
70 #if defined(HAVE_SYS_WAIT_H)
71 #include <sys/wait.h>
72 #endif
73 #if defined(HAVE_LIMITS_H)
74 #include <limits.h>
75 #endif
76 #if defined(HAVE_FCNTL_H)
77 #include <fcntl.h>
78 #endif
79
80 #if defined(HAVE_SYS_RESOURCES_H)
81 #include <sys/resource.h>
82 #endif
83
84 #if DXD_HAS_LIBIOP
85
86 #ifndef WSTOPSIG
87 #define WSTOPSIG(status) ((status).w_stopsig)
88 #define WTERMSIG(status) ((status).w_termsig)
89 #define WEXITSTATUS(status) ((status).w_retcode)
90 #endif
91
92 #endif
93
94 #if defined(HAVE_SYS_SELECT_H)
95 #include <sys/select.h>
96 #endif
97
98 #if defined(HAVE_SYS_SYSMP_H)
99 #include <sys/sysmp.h>
100 #endif
101 #if defined(HAVE_SYS_SYSTEMCFG_H)
102 # include <sys/systemcfg.h>
103 #endif
104
105 #if DXD_HAS_LIBIOP
106 #include <sys/svs.h>
107 #endif
108
109 /* On solaris exit seems to not work properly mp, the parent hangs around and never exits. */
110 #if solaris
111 #define exit(x) _exit(x)
112 #endif
113
114 #define READ_I_THRESHHOLD 0.05 /* how often to ioctl fd */
115 /*#define READ_S_THRESHHOLD 5.0*/ /* how often to select fd */
116 #define MAIN_TIMING 1
117
118 #define CHECK_INIT(_i, what)\
119 if ((_i) != OK) ExInitFailed (what)
120
121 #include "dxmain.h"
122 #include "config.h"
123 #include "background.h"
124 #include "parse.h"
125 #include "d.h"
126 #include "graph.h"
127 #include "rq.h"
128 #include "graphqueue.h"
129 #include "status.h"
130 #include "log.h"
131 #include "packet.h"
132 #include "exobject.h"
133 #include "sysvars.h"
134 #include "version.h"
135 #include "vcr.h"
136 #include "swap.h"
137 #include "_macro.h"
138 #include "_variable.h"
139 #include "parsemdf.h"
140 #include "command.h"
141 #include "pendingcmds.h"
142 #include "userinter.h"
143 #include "nodeb.h"
144 #include "lex.h"
145 #include "evalgraph.h"
146 #include "function.h"
147 #include "rih.h"
148 #include "task.h"
149 #include "remote.h"
150 #include "socket.h"
151 #include "../libdx/diskio.h"
152 #include "instrument.h"
153
154 #ifdef DXD_LICENSED_VERSION
155 #include "license.h"
156 static int exLicenseSelf = FALSE;
157 lictype _dxd_exForcedLicense = NOLIC; /* Is the given license forced */
158 int _dxd_ExHasLicense = FALSE;
159 #endif
160
161 #ifndef OPEN_MAX
162 #define OPEN_MAX sysconf(_SC_OPEN_MAX)
163 #endif
164
165 static int extestport = -1;
166 static char extesthost[80];
167
168 /* Functions defined in libdx or programatically defined */
169
170 extern int DXConnectToServer(char *host, int pport); /* from libdx/client.c */
171 extern void _dxfTraceObjects(int d); /* from libdx/object.c */
172 extern void _dxf_user_modules(); /* from libdx/ */
173 extern void _dxf_private_modules(); /* from libdx/ */
174 extern Error user_cleanup(); /* from libdx/userinit.c */
175
176 extern void _dxfcleanup_mem(); /* from libdx/mem.c */
177 extern int _dxf_GetPhysicalProcs(); /* from libdx/memory.c */
178 extern Error ExHostToFQDN( const char host[], char fqdn[MAXHOSTNAMELEN] );
179 /* from remote.c */
180 extern Error user_slave_cleanup(); /* from userinit.c */
181
182 /*
183 * How often to check for registered input handlers
184 */
185
186 #define EX_RIH_FREQUENCY 10.0
187 #define EX_RIH_INTERVAL 1.0 / EX_RIH_FREQUENCY
188
189
190 static int exParent = FALSE;
191 static int exParent_RQread_fd;
192 static int exParent_RQwrite_fd;
193 static int exChParent_RQread_fd;
194
195 static double read_i_threshhold = READ_I_THRESHHOLD;
196 /*static double read_s_threshhold = READ_S_THRESHHOLD;*/
197
198 static int maxMemory = 0; /* in MB -- 0 implies library default */
199
200 static int nprocs;
201 static int nphysprocs;
202
203 static int processor_status_on = FALSE;
204
205 PATHTAG _dxd_pathtags = {0, 0, NULL};
206 DPGRAPHSTAT _dxd_dpgraphstat = {0, 0, NULL};
207 DPHOSTS *_dxd_dphosts = NULL;
208 #if defined(DXD_USE_MUTEX_LOCKS) && DXD_USE_MUTEX_LOCKS==1
209 lock_type _dxd_dphostslock;
210 #else
211 lock_type _dxd_dphostslock = 0;
212 #endif
213 PGASSIGN _dxd_pgassign = {0, 0, NULL};
214 ;
215 SLAVEPEERS _dxd_slavepeers = {0, 0, NULL};
216 ;
217
218 int _dxd_exCacheOn = TRUE; /* use cache */
219 int _dxd_exIntraGraphSerialize = TRUE;
220 int _dxd_exDebug = FALSE;
221 int _dxd_exGoneMP = FALSE; /* set true after forking */
222 int _dxd_exRemote = FALSE;
223 int _dxd_exRemoteSlave = FALSE;
224 int _dxd_exRunningSingleProcess = TRUE; /* set with nphysprocs/nprocs */
225 int _dxd_exShowTiming = FALSE;
226 int _dxd_exShowTrace = FALSE;
227 int _dxd_exShowBells = FALSE;
228 int _dxd_exSkipExecution = FALSE;
229 int _dxd_exRshInput = FALSE;
230 int _dxd_exIsatty = FALSE;
231
232 SFILE *_dxd_exSockFD = NULL;
233 static SFILE *_pIfd = NULL;
234
235 static int logcache = FALSE;
236 static int logerr = 0;
237 int _dxd_exDebugConnect = FALSE;
238 int _dxd_exRemoteUIMsg = FALSE;
239
240 char *_dxd_exHostName = NULL;
241 int _dxd_exPPID = 0; /* parent's process id */
242 int *_dxd_exTerminating = NULL; /* flag set when dx is exiting */
243 int _dxd_exSelectReturnedInput = FALSE; /* flag set when select returned from yyin */
244 Context *_dxd_exContext = NULL; /* structure for context information */
245 int _dxd_exMyPID = 0; /* pid of the process */
246 int _dxd_exMasterfd = -1; /* slave to master file descriptor */
247 int _dxd_exSlaveId = 0; /* slave number */
248 int _dxd_exSwapMsg = 0; /* do we need to swap msg from peer? */
249 /* startup of slave as finished, send msgs OK */
250 int *_dxd_exNSlaves = NULL; /* number of distributed slaves */
251 int *_dxd_extoplevelloop = NULL; /* looping at top level of graph */
252
253 int _dxd_exErrorPrintLevel = 3;
254
255 int _dxd_exEnableDebug = 0;
256 long _dxd_exMarkMask = 0; /* DXMarkTime enable mask */
257 static int MarkModules = FALSE;
258
259 int _dxd_exParseAhead = TRUE;
260 int _dxd_exSParseAhead = 0;
261
262 static char *_pIstr = "stdin";
263
264 static char **exenvp = NULL;
265
266 #define MDF_MAX 20
267 static char *mdffiles[MDF_MAX];
268 static int nmdfs = 0;
269
270
271 /* Common routines added for distributed processing */
272
273 /*
274 * All the main helper functions.
275 */
276
277 /*
278 * This one's used externally in DODX RunOnSlaves
279 */
280 int ExCheckInput(void);
281 void ExQuit(void);
282 void _dxf_ExPromptSet(char *var, char *val);
283
284 static int ExCheckGraphQueue (int);
285 static int ExCheckRunqueue (int graphId);
286 static void ExCheckTerminate (void);
287 static void ExChildProcess (void);
288 static void ExCleanup (void);
289 static void ExConnectInput (void);
290 static void ExCopyright (int);
291 static int ExFindPID (int pid);
292 static void ExForkChildren (void);
293 static void ExInitialize (void);
294 static void ExInitFailed (char *message);
295 static void ExMainLoop (void);
296 static void ExMainLoopMaster (void);
297 static void ExMainLoopSlave (void);
298 static void ExParallelMaster (void);
299 static void ExProcessArgs (int argc, char **argv);
300 static void ExSettings (void);
301 static void ExUsage (char *name);
302 static void ExVersion (void);
303 static int ExFromMasterInputHndlr (int fd, Pointer p);
304
305 #if !defined(intelnt) && !defined(WIN32)
306 extern int DXForkChild(int);
307 #endif
308
309 #if DXD_EXEC_WAIT_PROCESS
310 static void ExParentProcess (void);
311 #endif
312
313 #if HAVE_SIGQUIT
314 static void ExSigQuit(int);
315 #endif
316 #if HAVE_SIGPIPE
317 static void ExSigPipe(int);
318 #endif
319 #if HAVE_SIGDANGER
320 static void ExSigDanger (int);
321 #endif
322 #if DXD_EXEC_WAIT_PROCESS
323 static void ExKillChildren(void);
324 #endif
325
326 EXDictionary _dxd_exGlobalDict = NULL;
327
328 static struct child
329 {
330 int pid;
331 int RQwrite_fd;
332 }
333 *children;
334
335 lock_type *childtbl_lock = NULL;
336
337 static volatile int *exReady;
338
DXmain(int argc,char ** argv,char ** envp)339 int DXmain (int argc, char **argv, char **envp)
340 {
341 int save_errorlevel=0;
342 #if HAVE_SYS_CORE_H
343
344 struct rlimit rl;
345 #endif
346
347 exenvp = envp;
348
349 #if HAVE_SYS_CORE_H
350
351 getrlimit (RLIMIT_CORE, &rl);
352 rl.rlim_cur = 0;
353 setrlimit (RLIMIT_CORE, &rl);
354 #endif
355
356 nphysprocs = _dxf_GetPhysicalProcs();
357
358 if(nphysprocs > 3)
359 nprocs = (int)(nphysprocs / 2);
360 else
361 nprocs = (nphysprocs > 1) ? 2 : 1;
362
363 #if HAVE_SIGDANGER
364 signal (SIGDANGER, ExSigDanger);
365 #endif
366
367 #if HAVE_SIGPIPE
368 signal(SIGPIPE, ExSigPipe);
369 #endif
370
371 #if HAVE_SIGQUIT
372 signal(SIGQUIT, ExSigQuit);
373 #endif
374
375 ExProcessArgs (argc, argv);
376
377 /* boolean: if UP machine, or user asked for -p1 on MP machine */
378 _dxd_exRunningSingleProcess = (nphysprocs == 1 || nprocs == 1);
379
380 /* if running single-process, we don't need the overhead of locking */
381 DXenable_locks( !_dxd_exRunningSingleProcess );
382
383 /* we will turn off parse ahead when we get a sync */
384 /* so save original state */
385 _dxd_exSParseAhead = _dxd_exParseAhead;
386 if (_dxd_exRemoteSlave) {
387 /* turn off messages during initialization */
388 save_errorlevel = _dxd_exErrorPrintLevel;
389 _dxd_exErrorPrintLevel = -1;
390 } else
391 ExCopyright (! _dxd_exRemote);
392
393 ExInitialize (); /* perform all shared initializations */
394
395 #ifdef DXD_LICENSED_VERSION
396
397 if(!_dxd_exRemoteSlave)
398 ExLicenseFinish(); /* finish license stuff with libDX initialized */
399
400 #endif /* DXD_LICENSED_VERSION */
401
402 if(_dxd_exRemoteSlave) {
403 /* turn messages back on */
404 _dxd_exErrorPrintLevel = save_errorlevel;
405 }
406
407 #ifdef DXD_LICENSED_VERSION
408
409 if (!_dxd_exRemote || exLicenseSelf) {
410 if (_dxd_exRemoteSlave)
411 _dxd_ExHasLicense = TRUE;
412 else if (!ExGetPrimaryLicense()) {
413 DXMessage ("Could not get a license\n");
414 exit (-1);
415 }
416 }
417 #endif /* DXD_LICENSED_VERSION */
418
419 if(logerr > 0)
420 _dxf_ExLogError(logerr);
421
422 ExForkChildren (); /* create subprocesses */
423
424 #if DXD_EXEC_WAIT_PROCESS
425 /*
426 * This is the parent waiter process. It waits for children to die
427 * and either kills the others off if there was an error, or exits
428 * gracefully.
429 */
430 if ((nprocs > 1 && _dxd_exPPID == getpid ()) || _dxd_exMyPID == -1)
431 ExParentProcess ();
432
433 if (nprocs == 1 || _dxd_exPPID != getpid ())
434 ExChildProcess ();
435 #else
436
437 ExChildProcess ();
438 #endif
439
440
441 return (0);
442 }
443
444
_dxf_ExEnvp(void)445 char **_dxf_ExEnvp (void)
446 {
447 return (exenvp);
448 }
449
450 #if DXD_EXEC_WAIT_PROCESS
ExParentProcess()451 static void ExParentProcess ()
452 {
453 int pid;
454 int wstatus;
455 int fpid;
456
457 exParent = TRUE;
458 *exReady = TRUE;
459
460 /*
461 * Stop here to add child processes for debugging!
462 */
463
464 wait_on_child:
465 /* wait for a child to die */
466 while ((pid = wait (&wstatus)) < 0)
467 if (errno != EINTR)
468 break;
469
470 #ifdef DXD_LICENSED_VERSION
471 /* Getting a license causes one or two more children to be created.
472 * on an MP system we will get two licenses and have 2 dxshadows running
473 * for nodelock licenses dxshadow exits immediately. This caused the
474 * exec to think a child had terminated. We need to see if this child
475 * was a dxshadow process and if it was a nodelock license then it's
476 * OK and we should go back to waiting on our children. In the case that
477 * dxshadow died for a concurrent license we will print out an error
478 * message and terminate. */
479 fpid = _dxfCheckLicenseChild(pid);
480 if(fpid == 0) /* we had a node locked license, continue to wait on child */
481 goto wait_on_child;
482 if(fpid == -1)
483 #endif
484
485 fpid = ExFindPID (pid);
486 /* process not in child table so use pid in error messages */
487 if(fpid < 0)
488 fpid = pid;
489
490 /* child died, now figure out why */
491 if (WIFSTOPPED (wstatus)) {
492 printf ("child process %d (%d) stopped; stop signal = %d\n",
493 fpid, pid, WSTOPSIG (wstatus));
494 } else if (WIFSIGNALED (wstatus)) {
495 if (WTERMSIG (wstatus) != 9)
496 printf ("child process %d (%d) killed by signal = %d\n",
497 fpid, pid, WTERMSIG (wstatus));
498 } else if (WIFEXITED (wstatus)) {
499 printf ("child process %d (%d) exited, status = %d\n",
500 fpid, pid, WEXITSTATUS (wstatus));
501 } else {
502 printf ("child process %d (%d) broke wait\n", fpid, pid);
503 }
504
505 ExCleanup ();
506
507 printf ("\nparent exiting\n");
508 fflush (stdout);
509
510 exit (0);
511 }
512 #endif
513
514
ExChildProcess()515 static void ExChildProcess ()
516 {
517 /*
518 * Wait for all the children to appear and the parent to signal OK to
519 * start processing.
520 */
521 _dxf_ExInitTaskPerProc();
522
523 /* don't send out worker messages for slaves */
524 if(!_dxd_exRemoteSlave)
525 DXMessage ("#1060", getpid ());
526
527 while ((nprocs > 1) && (! *exReady))
528 ;
529
530 ExMainLoop ();
531 }
532
533
534
ExMainLoop()535 static void ExMainLoop ()
536 {
537 if (_dxd_exMyPID == 0 || nprocs == 1)
538 ExMainLoopMaster ();
539 else
540 ExMainLoopSlave ();
541 }
542
543
ExMainLoopSlave()544 static void ExMainLoopSlave ()
545 {
546 int ret = TRUE;
547 int RQ_fd;
548 char c;
549
550 set_status (PS_EXECUTIVE);
551
552 RQ_fd = exParent_RQread_fd;
553
554 while (! *_dxd_exTerminating) {
555 ret = _dxf_ExRQPending () && ExCheckRunqueue (0);
556 if(! ret) {
557 if (_dxd_exMyPID == 1) {
558 if(_dxf_ExIsExecuting())
559 _dxf_ExCheckRIH ();
560 else
561 _dxf_ExCheckRIHBlock (-1);
562 } else
563 read(RQ_fd, &c, 1);
564 }
565 }
566 user_slave_cleanup();
567 }
568
569
570 /*
571 * ExMainLoopMaster -- This is the main loop executed by the master processor.
572 * The loop is different depending upon if this is the only processor (nprocs
573 * == 1) or if it is one of several, and thus the chief delegator. In the
574 * multiprocessor case, the principal task of the master is to make modules
575 * available to run (put them in the run queue) as quickly as possible, and
576 * only if there is nothing else for it to do, to try to run something.
577 * The function is different in the uniprocessor case, where this is the only
578 * loop being run. In this case, one tries to empty the run queue, then the
579 * module queue, then the graph queue, ....
580 *
581 * Note that all things that are only needed by the master should be inited
582 * here so that we don't waste the slaves' local memory.
583 */
584
585 #define MAIN_LOOP_CONTINUE {naptime = 0; goto main_loop_continue;}
586
587 #if TIMEOUT_DX
588 /* right now this only works for sgi, it's not being used now but it should
589 be changed to run on all machines if you want to do a timeout */
590 /* if idle for 30 minutes, kill it */
591 #define NAPTIME (CLK_TCK >> 2)
592 #define NAPDEAD (30 * 60 * CLK_TCK)
593 #endif
594
ExMainLoopMaster()595 static void ExMainLoopMaster ()
596 {
597 #if defined(DX_NATIVE_WINDOWS)
598 MSG msg;
599 #endif
600 /*
601 * Module definitions should be put into the dictionary before
602 * macro definitions which may occur in _dxf_ExParseInit (.dxrc files).
603 */
604
605 _dxf_user_modules ();
606 _dxf_private_modules ();
607 _dxf_ExInitRemote ();
608 _dxf_ExFunctionDone ();
609 CHECK_INIT (_dxf_ExParseInit (_pIstr, _pIfd), "reading .dxrc init file");
610
611 #if sgi
612
613 if (nprocs > 1)
614 sleep (1);
615 #endif
616
617 set_status (PS_EXECUTIVE);
618
619 if(_dxd_exRemoteSlave) {
620 int fd;
621 if(extestport < 0)
622 _dxf_ExDie("No port specified for slave to connect to");
623 fd = DXConnectToServer(extesthost, extestport);
624 if(fd < 0)
625 _dxf_ExDie("couldn't connect to socket %d\n", extestport);
626 printf("connected to %s:%4d\n", extesthost, extestport);
627 _dxd_exMasterfd = fd;
628 DXRegisterInputHandler(ExFromMasterInputHndlr, fd, NULL);
629 for (;;) {
630 loop_slave_continue:
631 ExCheckTerminate ();
632 if (_dxf_ExRQPending () && ExCheckRunqueue (0)) {
633 /* always check rih so socket doesn't get blocked */
634 _dxf_ExCheckRIH ();
635 goto loop_slave_continue;
636 }
637 if(nprocs == 1)
638 _dxf_ExCheckRIHBlock (_dxd_exMasterfd);
639 else {
640 if(_dxf_ExCheckRIH ())
641 goto loop_slave_continue;
642 #if sgi
643
644 else {
645 set_status (PS_NAPPING);
646 sginap (0);
647 set_status (PS_EXECUTIVE);
648 }
649 #endif
650
651 }
652 }
653 } else
654 _dxd_exSlaveId = 0;
655
656 while (1) /* naptime */
657 {
658
659 ExMarkTimeLocal (4, "main:top");
660 DXqflush ();
661
662 IFINSTRUMENT (++exInstrument[_dxd_exMyPID].numMasterTry);
663
664 /*
665 * have we achieved termination condition
666 */
667 ExCheckTerminate ();
668
669 if (nprocs > 1)
670 ExParallelMaster ();
671 else
672 {
673 _dxf_ExCheckRIH ();
674 ExMarkTimeLocal (4, "main:chrq");
675 if (_dxf_ExRQPending () && ExCheckRunqueue (0)) {
676 if (_dxd_exParseAhead)
677 ExCheckInput ();
678 continue;
679 }
680
681 _dxf_RunPendingCmds();
682
683 if (_dxd_exParseAhead) {
684 ExMarkTimeLocal (4, "main:chin");
685 if (ExCheckInput ())
686 continue;
687 }
688
689 ExMarkTimeLocal (4, "main:chgq");
690 if (ExCheckGraphQueue (-1))
691 continue;
692
693 if (! _dxd_exParseAhead) {
694 /* if we get here there is nothing in the queues */
695 /* restore parse ahead in case it was changed */
696 _dxd_exParseAhead = _dxd_exSParseAhead;
697 ExMarkTimeLocal (4, "main:chin");
698 if (ExCheckInput ())
699 continue;
700 }
701
702 ExMarkTimeLocal (4, "main:chbg");
703 if (_dxf_ExCheckBackground (_dxd_exGlobalDict, FALSE))
704 continue;
705
706 ExMarkTimeLocal (4, "main:chVCR");
707 if (_dxf_ExCheckVCR (_dxd_exGlobalDict, FALSE))
708 continue;
709
710 #if defined(intelnt) || defined(WIN32)
711 SleepEx(100, TRUE);
712 #endif
713 #if defined(DX_NATIVE_WINDOWS)
714
715 while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
716 TranslateMessage(&msg);
717 DispatchMessage(&msg);
718 }
719 #endif
720 #if defined(DDX)
721 {
722 extern Error SlaveBcastLoop(int, Pointer);
723 extern int GetMPINodeId();
724 if (GetMPINodeId() == 0)
725 _dxf_ExCheckRIHBlock (SFILEfileno (yyin));
726 else {
727 SlaveBcastLoop(0, NULL);
728 _dxf_ExCheckRIH ();
729 }
730 }
731 #else
732 #ifndef DXD_NOBLOCK_SELECT
733 ExMarkTimeLocal (4, "main:chRIH");
734 _dxf_ExCheckRIHBlock (SFILEfileno (yyin));
735 #endif
736 #endif
737
738 }
739
740 /* main_loop_continue: */
741 continue;
742 }
743
744 _dxf_CleanupPendingCmdList();
745 }
746
747 #if DXD_EXEC_WAIT_PROCESS
748 /*
749 * Let all of the remaining children know they are to die.
750 */
ExKillChildren()751 static void ExKillChildren ()
752 {
753 int i;
754
755 if (! (_dxd_exMyPID == 0 && nprocs == 1))
756 for (i = 0; i < nprocs && i < nphysprocs; i++)
757 kill (children[i].pid, SIGKILL);
758
759 #if DXD_PROCESSOR_STATUS
760
761 if (_dxd_exStatusPID)
762 kill (_dxd_exStatusPID, SIGKILL);
763 #endif
764 }
765 #endif
766
767
768 #define EMESS "Error during Initialization\n"
769
ExInitFailed(char * message)770 static void ExInitFailed (char *message)
771 {
772 char *cp;
773
774 /*
775 * print a message before exiting saying why we can't start up.
776 */
777
778 write(fileno (stdout), EMESS, strlen(EMESS));
779
780 cp = DXGetErrorMessage();
781 if (cp)
782 write (fileno (stdout), cp, strlen (cp));
783 write(fileno (stdout), "\n", 1);
784
785 if (message)
786 write(fileno (stdout), message, strlen (message));
787 write(fileno (stdout), "\n", 1);
788
789 exit (0);
790 }
791
792
_dxf_ExDie(char * format,...)793 void _dxf_ExDie (char *format, ...)
794 {
795 char buffer[1024];
796 va_list arg;
797
798 /* don't add a space before format in the next line or it won't
799 * compile with the metaware compiler.
800 */
801 va_start(arg,format);
802 vsprintf(buffer, format, arg);
803 va_end(arg);
804
805 if(_dxd_exRemoteSlave && _dxd_exMasterfd >= 0)
806 DXUIMessage("ERROR", buffer);
807 else {
808 fputs (buffer, stdout);
809 fputs ("\n", stdout);
810 fflush (stdout);
811 }
812
813 exit (-1);
814 }
815
816 #if DXD_IS_MP
817 #define VALID_ARGS "BC:cdDE:F:H:hi:L:lmM:p:PrRsStTUuvVX"
818 #else
819 #define VALID_ARGS "BC:cdDE:F:H:hi:L:lmM:p:rRsStTUuvVX"
820 #endif
821
822 /*
823 * Process command line arguments.
824 */
ExProcessArgs(int argc,char ** argv)825 static void ExProcessArgs (int argc, char **argv)
826 {
827 int opt;
828
829 /*
830 * Loop over the command line looking for arguments.
831 */
832 while ((opt = getopt (argc, argv, VALID_ARGS)) != EOF) {
833 switch (opt) {
834 case 'B':
835 _dxd_exShowBells = TRUE;
836 break;
837 case 'C':
838 extestport = atoi(optarg);
839 break;
840 case 'D':
841 _dxd_exDebugConnect = TRUE;
842 break;
843 case 'E':
844 _dxd_exErrorPrintLevel = atoi (optarg);
845 break;
846 case 'F':
847 if (optarg == NULL) {
848 fprintf(stdout, "missing MDF filename");
849 ExUsage (argv[0]);
850 }
851 if (nmdfs >= MDF_MAX) {
852 fprintf(stdout, "too many -F files specified");
853 ExUsage (argv[0]);
854 }
855 mdffiles[nmdfs++] = optarg;
856 break;
857 case 'H':
858 strcpy(extesthost, optarg);
859 break;
860 case 'L':
861 #ifdef DXD_LICENSED_VERSION
862
863 if (optarg && !strcmp(optarg,"runtime"))
864 _dxd_exForcedLicense = RTLIC;
865 else if (optarg && !strcmp(optarg,"develop"))
866 _dxd_exForcedLicense = DXLIC;
867 else if (optarg && !strcmp(optarg,"self"))
868 exLicenseSelf = TRUE;
869 else {
870 fprintf (stdout,
871 "Invalid license specification '%s'\n",
872 optarg ? optarg : "");
873 ExUsage (argv[0]);
874 }
875 #else
876 #if 0 /* This causes a malloc() which causes problems on the PVS */
877 fprintf (stdout,
878 "L option ignored on non-license managed hosts\n");
879 #endif
880 #endif /* DXD_LICENSED_VERSION */
881
882 break;
883 case 'M':
884 if (optarg == NULL ||
885 ! isdigit (*optarg) ||
886 (maxMemory = atoi (optarg)) == 0) {
887 fprintf (stdout,
888 "Invalid memory specification '%s'\n",
889 optarg);
890 ExUsage (argv[0]);
891 }
892 #ifndef ENABLE_LARGE_ARENAS
893 {
894 int mlim = (0x7fffffff >> 20); /* divide by 1 meg */
895 if (maxMemory > mlim)
896 maxMemory = mlim;
897 }
898 #endif
899
900 /*
901 * NOTE: If we don't call DXmemsize then the memory allocator
902 * will default to something appropriate for the machine that we
903 * are currently running on.
904 */
905
906 if (maxMemory > 0)
907 while (DXmemsize (MEGA ((ulong)maxMemory)) != OK)
908 maxMemory--;
909 break;
910
911 #if DXD_PROCESSOR_STATUS
912
913 case 'P':
914 processor_status_on = TRUE;
915 break;
916 #endif
917
918 case 'R':
919 _dxd_exRshInput = TRUE;
920 /*read_s_threshhold = READ_I_THRESHHOLD;*/
921 break;
922 case 'S':
923 _dxd_exIntraGraphSerialize = FALSE;
924 break;
925 case 'T':
926 _dxd_exShowTrace = TRUE;
927 break;
928 case 'U':
929 _dxd_exRemoteUIMsg = TRUE;
930 break;
931 case 'X':
932 _dxd_exSkipExecution = TRUE;
933 break;
934 case 'V':
935 _dxd_exEnableDebug = TRUE;
936 break;
937
938 case 'c':
939 _dxd_exCacheOn = FALSE;
940 break;
941 case 'd':
942 _dxd_exDebug = TRUE;
943 break;
944 case 'h':
945 ExUsage (argv[0]);
946 break;
947 case 'i':
948 read_i_threshhold = atof (optarg);
949 break;
950 case 'l':
951 logcache = TRUE;
952 break;
953 case 'm':
954 MarkModules = TRUE;
955 break;
956 case 'p':
957 if (optarg == NULL ||
958 ! isdigit (*optarg) ||
959 (nprocs = atoi (optarg)) == 0) {
960 fprintf (stdout,
961 "Invalid processor specification '%s'\n",
962 optarg);
963 ExUsage (argv[0]);
964 }
965 break;
966
967 case 'r':
968 _dxd_exRemote = TRUE;
969 break;
970 case 's':
971 _dxd_exRemoteSlave = TRUE;
972 break;
973 case 't':
974 _dxd_exShowTiming = 1;
975 break;
976 case 'u':
977 _dxd_exParseAhead = FALSE;
978 break;
979 case 'v':
980 ExVersion ();
981 break;
982
983 default :
984 ExUsage (argv[0]);
985 break;
986 }
987 }
988 }
989
990
ExCopyright(int p)991 static void ExCopyright (int p)
992 {
993 if (p) {
994 write (fileno (stdout), DXD_COPYRIGHT_STRING,
995 strlen (DXD_COPYRIGHT_STRING));
996 write (fileno (stdout), "\n", 1);
997 }
998 }
999
1000
ExUsage(char * name)1001 static void ExUsage (char *name)
1002 {
1003 ExCopyright (TRUE);
1004 fprintf (stdout, "usage: %s ", name);
1005 fprintf (stdout, "[-B]");
1006 fprintf (stdout, "[-c]");
1007 fprintf (stdout, "[-d]");
1008 fprintf (stdout, "[-E #]");
1009 fprintf (stdout, "[-F file]");
1010 fprintf (stdout, "[-i #]");
1011 fprintf (stdout, "[-l]");
1012 fprintf (stdout, "[-m]");
1013 fprintf (stdout, "[-M #]");
1014 #if DXD_IS_MP
1015
1016 fprintf (stdout, "[-p #]");
1017 #endif
1018 #if DXD_PROCESSOR_STATUS
1019
1020 fprintf (stdout, "[-P]");
1021 #endif
1022
1023 fprintf (stdout, "[-r]");
1024 fprintf (stdout, "[-R]");
1025 fprintf (stdout, "[-S]");
1026 fprintf (stdout, "[-t]");
1027 fprintf (stdout, "[-T]");
1028 fprintf (stdout, "[-u]");
1029 fprintf (stdout, "[-v]");
1030 fprintf (stdout, "\n");
1031
1032 fprintf (stdout, " -B enable UI node highlighting\n");
1033 fprintf (stdout, " -c disable lookaside cache\n");
1034 fprintf (stdout, " -d enable memory debug\n");
1035 fprintf (stdout, " -E set error print level (default = %d)\n",
1036 _dxd_exErrorPrintLevel);
1037 fprintf (stdout, " -F load a module definition file\n");
1038 fprintf (stdout, " -i set read delay threshhold (default = %g)\n",
1039 read_i_threshhold);
1040 fprintf (stdout, " -l toggle logging to dx.log (default = %s)\n",
1041 logcache ? "on" : "off");
1042 fprintf (stdout, " -L force a license type (runtime or develop)\n");
1043
1044 fprintf (stdout, " -m mark module execution times\n");
1045 fprintf (stdout, " -M limit global memory (default = %d)\n",
1046 maxMemory);
1047
1048 #if DXD_IS_MP
1049
1050 fprintf (stdout, " -p number of processors (default = %d)\n",
1051 nprocs);
1052 #endif
1053 #if DXD_PROCESSOR_STATUS
1054
1055 fprintf (stdout, " -P toggle processor status (default = %s)\n",
1056 processor_status_on ? "on" : "off");
1057 #endif
1058
1059 fprintf (stdout, " -r turn on remote execution\n");
1060 fprintf (stdout, " -R started with rsh but not in remote mode\n");
1061
1062 fprintf (stdout, " -S intra graph serialization (default = %s)\n",
1063 _dxd_exIntraGraphSerialize ? "on" : "off");
1064
1065 fprintf (stdout, " -t enable exec timing & printing\n");
1066 fprintf (stdout, " -T trace module executions\n");
1067 fprintf (stdout, " -u disable parse ahead (for leak detection)\n");
1068
1069 fprintf (stdout, " -v display executive version number\n");
1070 fprintf (stdout, " -V enables printing of executive DXDebug messages\n");
1071 fflush (stdout);
1072
1073 exit (2);
1074 }
1075
1076
ExVersion()1077 static void ExVersion ()
1078 {
1079 char buf[128];
1080
1081 /*
1082 * On the sun, using fprintf() makes _initmemory() get called, which
1083 * causes unwanted memory messages about arena sizes. So use write()
1084 * directly. this is what we are putting together:
1085 * printf("%s, version %02d.%02d.%04d (%s, %s)\n"
1086 *
1087 * or
1088 * printf("%s, version %02d.%02d.%04d%c (%s, %s)\n"
1089 * (note the letter following the revision number)
1090 */
1091 fflush(stdout);
1092 strcpy(buf, EX_NAME);
1093 strcat(buf, ", version ");
1094 strcat(buf, DXD_VERSION_STRING);
1095
1096 strcat(buf, " (");
1097 strcat(buf, __TIME__);
1098 strcat(buf, ", ");
1099 strcat(buf, __DATE__);
1100 strcat(buf, ")\n");
1101 write(fileno(stdout),buf,strlen(buf));
1102
1103 exit (0);
1104 }
1105
_dxf_ExInitPromptVars()1106 void _dxf_ExInitPromptVars()
1107 {
1108 _dxf_ExPromptSet(PROMPT_ID_PROMPT,EX_PROMPT);
1109 _dxf_ExPromptSet(PROMPT_ID_CPROMPT,EX_CPROMPT);
1110 }
1111
1112
_dxf_ExInitSystemVars()1113 void _dxf_ExInitSystemVars ()
1114 {
1115 _dxf_ExInitVCRVars ();
1116 if(!_dxd_exRemoteSlave)
1117 _dxf_ExInitPromptVars ();
1118 }
1119
1120
1121 /*
1122 * Perform all initializations necessary to run the executive.
1123 */
ExConnectInput()1124 static void ExConnectInput ()
1125 {
1126 int port;
1127 SFILE *_dxf_ExInitServer(int);
1128
1129 if (_dxd_exRemote) {
1130 _dxf_ExGetSocket (NULL, &port);
1131 _dxd_exSockFD = _dxf_ExInitServer (port);
1132
1133 if(_dxf_ExInitPacket() == ERROR)
1134 ExInitFailed ("can't make UI connection");
1135
1136 if (_dxd_exSockFD == NULL)
1137 ExInitFailed ("can't make UI connection");
1138 _pIfd = _dxd_exSockFD;
1139 _pIstr = "UI";
1140 _dxd_exIsatty = 0;
1141 } else {
1142 FILE *fptr;
1143 extern void GetBaseConnection(FILE **fptr, char **str);
1144 GetBaseConnection(&fptr, &_pIstr);
1145 _pIfd = FILEToSFILE(fptr);
1146 _dxd_exIsatty = SFILEisatty(_pIfd);
1147 }
1148 }
1149
1150
ExInitialize()1151 static void ExInitialize ()
1152 {
1153 int i;
1154 int n;
1155 int nasked;
1156 char *mm;
1157
1158 _dxd_exPPID = getpid ();
1159
1160 if (logcache)
1161 logerr = _dxf_ExLogOpen ();
1162
1163 /*
1164 * Set up the library
1165 */
1166
1167 /* save this until we initialize the library. then we can use
1168 * the message code to warn the user if they asked for more procs
1169 * than are available
1170 */
1171 nasked = nprocs;
1172
1173 #if DXD_IS_MP
1174
1175 if (nprocs <= 0 || nprocs > nphysprocs) {
1176 nprocs = nphysprocs;
1177 }
1178 #else
1179 if (nprocs > 1) {
1180 nprocs = 1;
1181 }
1182 #endif
1183
1184 #if DXD_LICENSED_VERSION
1185
1186 if(nprocs > 1) {
1187 /* we call LicenseFinish later when it's safe */
1188 if (!ExGetLicense(MPLIC,FALSE))
1189 nprocs = 1;
1190
1191 }
1192
1193 #endif /* DXD_LICENSED_VERSION */
1194
1195
1196
1197 DXProcessors (nprocs); /* set number of processors before */
1198 /* initializing the library */
1199
1200 CHECK_INIT (DXinitdx (), "cannot initialize DX library");
1201
1202 /* connect to server BEFORE rest of inits which can produce messages */
1203 ExConnectInput ();
1204
1205 if((_dxd_exContext = (Context *)DXAllocate(sizeof(Context))) == NULL)
1206 ExInitFailed ("can't allocate memory");
1207 _dxd_exContext->graphId = 0;
1208 _dxd_exContext->userId = 0;
1209 _dxd_exContext->program = NULL;
1210 _dxd_exContext->subp = NULL;
1211
1212 if((_dxd_exHostName = (char *)DXAllocate(MAXHOSTNAMELEN)) == NULL)
1213 ExInitFailed ("can't allocate memory");
1214 gethostname(_dxd_exHostName, MAXHOSTNAMELEN);
1215 if ( ExHostToFQDN(_dxd_exHostName, _dxd_exHostName ) == ERROR )
1216 ExInitFailed ("ExHostToFQDN failed");
1217
1218 /* now that lib is initialized, we can use DXMessage() if needed */
1219 #if DXD_IS_MP
1220
1221 if (nasked <= 0 || nasked > nphysprocs) {
1222 if(!_dxd_exRemoteSlave)
1223 DXUIMessage ("WARNING MSGERRUP",
1224 "requested %d, using %d processors",
1225 nasked, nphysprocs);
1226 }
1227 #else
1228 if (nasked > 1) {
1229 if(!_dxd_exRemoteSlave)
1230 DXMessage ("#1080");
1231 }
1232 #endif
1233
1234 fflush (stdout);
1235
1236 DXSetErrorExit (0); /* don't allow error exits */
1237 DXEnableDebug ("0", _dxd_exShowTrace);
1238 _dxfTraceObjects (0); /* don't be verbose about objects */
1239 if (_dxd_exShowTiming > 1)
1240 DXTraceTime (TRUE);
1241 DXRegisterScavenger (_dxf_ExReclaimMemory);
1242
1243 if (MarkModules)
1244 _dxd_exMarkMask = 0x20;
1245 else {
1246 if ((mm = (char *) getenv ("EXMARKMASK")) != NULL)
1247 _dxd_exMarkMask = strtol (mm, 0, 0);
1248 else
1249 _dxd_exMarkMask = 0x3;
1250 }
1251
1252 CHECK_INIT (_dxf_initdisk (), "cannot initialize external disk array");
1253
1254 ExSettings ();
1255
1256 CHECK_INIT (_dxf_EXO_init (), "cannot initialize executive object dictionary");
1257
1258 if ((exReady = (volatile int *) DXAllocate (sizeof (volatile int))) == NULL)
1259 ExInitFailed ("can't allocate memory");
1260 *exReady = FALSE;
1261
1262 if ((children = (struct child *)
1263 DXAllocate (sizeof (struct child) * DXProcessors (0) + 1)) == NULL)
1264 ExInitFailed ("can't DXAllocate");
1265 if ((childtbl_lock = (lock_type *)DXAllocate(sizeof(lock_type))) == NULL)
1266 ExInitFailed ("can't DXAllocate");
1267 DXcreate_lock(childtbl_lock, "lock for child table");
1268
1269 if ((_dxd_exTerminating = (int *) DXAllocate (sizeof(int))) == NULL)
1270 ExInitFailed ("can't allocate memory");
1271 *_dxd_exTerminating = FALSE;
1272
1273 if ((_dxd_exNSlaves = (int *) DXAllocate (sizeof(int))) == NULL)
1274 ExInitFailed ("can't allocate memory");
1275 *_dxd_exNSlaves = 0;
1276
1277 if ((_dxd_extoplevelloop = (int *) DXAllocate (sizeof(int))) == NULL)
1278 ExInitFailed ("can't allocate memory");
1279 *_dxd_extoplevelloop = FALSE;
1280
1281 _dxd_exSlaveId = -1;
1282 _dxd_exSwapMsg = FALSE;
1283 _dxf_InitDPtableflag();
1284
1285 CHECK_INIT (_dxf_ExInitTask (nprocs), "cannot initialize task structures");
1286
1287 #if DXD_PROCESSOR_STATUS
1288
1289 CHECK_INIT (_dxf_ExInitStatus (nprocs, processor_status_on),
1290 "cannot initialize processor status display");
1291 #endif
1292
1293 n = MAXGRAPHS;
1294
1295 CHECK_INIT (_dxf_ExInitMemoryReclaim (),
1296 "cannot initialize memory reclaimation routines");
1297
1298 /* create the run queue */
1299 CHECK_INIT (_dxf_ExRQInit (), "cannot initialize the run queue");
1300
1301 n = MAXGRAPHS;
1302 /* don't allocate more graph slots than processors */
1303 n = (n > nprocs) ? nprocs : n;
1304 CHECK_INIT (_dxf_ExGQInit (n), "cannot initialize the graph queue");
1305
1306 /* locks for module symbol table */
1307 CHECK_INIT (_dxf_ModNameTablesInit(), "cannot initialize symbol table");
1308
1309 /* get root dictId before fork */
1310 _dxd_exGlobalDict = _dxf_ExDictionaryCreate (2048, TRUE, FALSE);
1311
1312 _dxd_dphosts =
1313 (DPHOSTS *)DXAllocate(sizeof(LIST(dphosts)));
1314 if(_dxd_dphosts == NULL)
1315 ExInitFailed ("can't allocate memory for distributed table");
1316 INIT_LIST(*_dxd_dphosts);
1317 DXcreate_lock (&_dxd_dphostslock, "HostTable's Lock");
1318 INIT_LIST(_dxd_pgassign);
1319 INIT_LIST(_dxd_slavepeers);
1320
1321 /* must happen after dictionary */
1322 CHECK_INIT (_dxf_ExInitVCR (_dxd_exGlobalDict), "cannot initialize the Sequencer");
1323 CHECK_INIT (_dxf_ExInitBackground (), "cannot initialize background processes");
1324 CHECK_INIT (_dxf_ExQueueGraphInit (), "cannot initialize for graph execution");
1325
1326 #if YYDEBUG != 0
1327
1328 yydebug = 0; /* don't bug me */
1329 #endif
1330
1331 CHECK_INIT (_dxf_ExCacheInit (), "cannot initialize the object cache");
1332 CHECK_INIT (_dxf_ExMacroInit (), "cannot initialize the macro dictionary");
1333 INIT_LIST(_dxd_pathtags);
1334
1335 /* this does NOT use CHECK_INIT because it shouldn't be a fatal
1336 * error to not find an mdf file. the loadmdf routine will set an
1337 * error message; if set, DXPrintError() will make it appear.
1338 * libdx is initialized at this point, so calling SetError, PrintError
1339 * and ResetError should be ok.
1340 */
1341 for (i=0; i<nmdfs; i++)
1342 if (DXLoadMDFFile (mdffiles[i]) == ERROR) {
1343 DXPrintError("MDF file");
1344 DXResetError();
1345 }
1346
1347 if (! _dxfLoadDefaultUserInteractors())
1348 ExInitFailed("Error loading user interactor files");
1349
1350
1351
1352 /*
1353 * System variables should be set before .dxrc processing too.
1354 */
1355
1356 _dxf_ExInitSystemVars ();
1357
1358 }
1359
1360
ExSettings()1361 static void ExSettings ()
1362 {
1363 ExDebug ("*1", "intra graph serialize %s",
1364 _dxd_exIntraGraphSerialize ? "ON" : "OFF");
1365 ExDebug ("*1", "lookaside caching %s",
1366 _dxd_exCacheOn ? "ON" : "OFF");
1367 ExDebug ("*1", "processors %d", nprocs);
1368 ExDebug ("*1", "status display %s",
1369 processor_status_on ? "ON" : "OFF");
1370 ExDebug ("*1", "execution log %s", logcache ? "ON" : "OFF");
1371 ExDebug ("*1", "");
1372 }
1373
1374
1375 /*
1376 * Have conditions for termination been met yet?
1377 */
1378
ExCheckTerminate()1379 static void ExCheckTerminate ()
1380 {
1381 int n = 3, i;
1382
1383 if (! (*_dxd_exTerminating))
1384 return;
1385
1386 /*
1387 * Make sure that nothing slipped in on us. Particularly from the
1388 * VCR operating on another processor.
1389 */
1390
1391 while (n--) {
1392 if (_dxf_ExRQPending ())
1393 return;
1394 if (! _dxf_ExGQAllDone ())
1395 return;
1396 if (_dxf_ExVCRRunning ())
1397 return;
1398 }
1399
1400 /*
1401 * signal childen to loop so they will see the terminate flag
1402 */
1403 for (i = 1; i < nprocs; i++)
1404 write(children[i].RQwrite_fd, "a", 1);
1405
1406 _dxf_ExCacheFlush (TRUE);
1407 _dxf_ExDictionaryPurge (_dxd_exGlobalDict);
1408
1409 /*
1410 * send out exit message before ExCleanup, ExCleanup
1411 * can get called multiple times. If a child exits first
1412 * ExCleanup gets called a second time by the parent
1413 * to clean up the rest of the children.
1414 */
1415 if(!_dxd_exRemoteSlave) {
1416 int peerwait = 0;
1417 _dxf_ExDistributeMsg(DM_EXIT, (Pointer)&peerwait, 0, TOSLAVES);
1418 } else
1419 close(_dxd_exMasterfd);
1420 ExCleanup ();
1421 exit(0);
1422 }
1423
1424
1425 /*
1426 * Error quit
1427 */
ExQuit()1428 void ExQuit()
1429 {
1430 int i;
1431
1432 (*_dxd_exTerminating) = 1;
1433
1434 /*
1435 * signal childen to loop so they will see
1436 * the terminate flag (if they are still there)
1437 */
1438 #if HAVE_SIGQUIT
1439
1440 for (i = 1; i < nprocs; i++)
1441 kill(children[i].pid, SIGQUIT);
1442 #endif
1443
1444 _dxf_ExCacheFlush (TRUE);
1445 _dxf_ExDictionaryPurge (_dxd_exGlobalDict);
1446
1447 /*
1448 * send out exit message before ExCleanup, ExCleanup
1449 * can get called multiple times. If a child exits first
1450 * ExCleanup gets called a second time by the parent
1451 * to clean up the rest of the children.
1452 */
1453 if(!_dxd_exRemoteSlave) {
1454 int peerwait = 0;
1455 _dxf_ExDistributeMsg(DM_EXIT,
1456 (Pointer)&peerwait, 0, TOSLAVES);
1457 } else
1458 close(_dxd_exMasterfd);
1459
1460 ExCleanup ();
1461 exit(1);
1462 }
1463
1464 /*
1465 * Perform any cleanups necessary to free up system resources.
1466 */
ExCleanup()1467 static void ExCleanup ()
1468 {
1469 int ok;
1470 int i,limit;
1471 dpgraphstat *index;
1472 PGassign *pgindex;
1473 SlavePeers *sindex;
1474
1475 user_cleanup();
1476
1477 if (MarkModules)
1478 DXPrintTimes ();
1479 ExDebug ("*1", "in ExCleanup");
1480
1481 #ifdef DXD_LICENSED_VERSION
1482
1483 _dxf_ExReleaseLicense();
1484 #endif
1485
1486 /* for MP machines it is possible that someone will be running only 1 */
1487 /* processor but will have the status window turned on. The status */
1488 /* windowing creates a new process so we have to clean that up right. */
1489 ok = ((exParent && _dxd_exMyPID==-1) || (nprocs == 1 && _dxd_exMyPID == 0 && ! processor_status_on));
1490
1491 if (! ok)
1492 exit (0);
1493
1494 FREE_LIST(_dxd_pathtags);
1495
1496 for (i = 0, limit = SIZE_LIST(_dxd_dpgraphstat); i < limit; ++i) {
1497 index = FETCH_LIST(_dxd_dpgraphstat, i);
1498 DXFree(index->prochostname);
1499 DXFree(index->procusername);
1500 if(index->options)
1501 DXFree(index->options);
1502 if(index->procfd > 0)
1503 close(index->procfd);
1504 }
1505 FREE_LIST(_dxd_dpgraphstat);
1506
1507 for (i = 0, limit = SIZE_LIST(_dxd_pgassign); i < limit; ++i) {
1508 pgindex = FETCH_LIST(_dxd_pgassign, i);
1509 DXFree(pgindex->pgname);
1510 pgindex->hostindex = -1;
1511 }
1512 FREE_LIST(_dxd_pgassign);
1513
1514 for (i = 0, limit = SIZE_LIST(_dxd_slavepeers); i < limit; ++i) {
1515 sindex = FETCH_LIST(_dxd_slavepeers, i);
1516 DXFree(sindex->peername);
1517 close(sindex->sfd);
1518 }
1519 FREE_LIST(_dxd_slavepeers);
1520
1521 _dxf_exitdisk ();
1522
1523 if(!_dxd_exRemoteSlave)
1524 DXMessage ("#1090");
1525
1526 #ifdef INSTRUMENT
1527
1528 ExPrintInstrument ();
1529 ExFreeInstrument();
1530 #endif
1531
1532 DXqflush ();
1533
1534 DXFree ((Pointer) exReady);
1535
1536 /* make sure there are no shared memory segments still waiting to */
1537 /* be attached to by other processes. */
1538 _dxfcleanup_mem();
1539
1540 /*
1541 * make sure other kids go away before we really start blowing things
1542 * away
1543 */
1544
1545 #if DXD_EXEC_WAIT_PROCESS
1546
1547 ExKillChildren ();
1548 #endif
1549
1550 if (logcache)
1551 _dxf_ExLogClose ();
1552
1553 return;
1554 }
1555
1556 /*
1557 * Fork off the child processes which will migrate to different physical
1558 * processors to give us our multi-processor support.
1559 */
ExForkChildren()1560 static void ExForkChildren ()
1561 {
1562 int pid;
1563 int i;
1564
1565 #ifdef INSTRUMENT
1566
1567 ExAllocateInstrument (nprocs);
1568 #endif
1569
1570 children[0].pid = getpid ();
1571
1572 /*
1573 * Don't fork if we are running uni-processor and were not creating
1574 * any other processes by creating a status window.
1575 */
1576
1577 if (nprocs == 1 && ! processor_status_on) {
1578 _dxd_exMyPID = ExFindPID (children[0].pid);
1579 if(_dxd_exMyPID < 0)
1580 _dxf_ExDie("Fork Children unable to get child id %d",
1581 children[0].pid);
1582
1583 return;
1584 }
1585
1586 #if !defined(intelnt) && !defined(WIN32)
1587
1588 /* set this before we fork and create separate data spaces. */
1589 _dxd_exGoneMP = TRUE;
1590
1591 #if DXD_HAS_LIBIOP
1592
1593 {
1594 int *GI = NULL;
1595 lock_type *LI = NULL;
1596 GI = (int *)DXAllocate(sizeof(int));
1597 LI = (lock_type *)DXAllocate(sizeof(lock_type));
1598 if(GI == NULL || LI == NULL)
1599 _dxf_ExDie("pfork setup failed");
1600 *GI = 0;
1601 if(!DXcreate_lock(LI, "pfork"))
1602 _dxf_ExDie("pfork create lock failed");
1603
1604 /* fork all processes at once */
1605 pid = pfork (nprocs - 1);
1606
1607 /* this code is forked and is run on all processes. *GI holds an */
1608 /* index into array of process ids. Lock and then increment */
1609 /* counter before filling in that array entry for each processor */
1610 DXlock(LI, 0);
1611 i = *GI;
1612 *GI += 1;
1613 DXunlock(LI, 0);
1614 children[i].pid = getpid ();
1615 }
1616 #else
1617 /* fork off processes for each of the processors */
1618 #if DXD_EXEC_WAIT_PROCESS
1619 for (i = 0; i < nprocs; i++)
1620 #else
1621
1622 for (i = 1; i < nprocs; i++)
1623 #endif
1624
1625 {
1626 int p;
1627
1628 #if DXD_EXEC_WAIT_PROCESS && !defined(DXD_MASTER_IS_P0)
1629
1630 if (i == nprocs-1)
1631 p = 0;
1632 else
1633 p = i + 1;
1634 #else
1635
1636 p = i;
1637 #endif
1638
1639 /* flush all output files prior to forking */
1640 fflush (stdout);
1641 fflush (stderr);
1642
1643 pid = DXForkChild(p);
1644
1645 if (pid == 0)
1646 {
1647 break;
1648 }
1649
1650 if (pid == -1)
1651 perror ("main: fork failed");
1652 }
1653 #endif
1654
1655 #if DXD_EXEC_WAIT_PROCESS
1656 /* don't pin parent process */
1657 if (_dxd_exPPID != getpid ()) {
1658 #endif
1659 DXlock(childtbl_lock, 0);
1660 _dxd_exMyPID = ExFindPID (getpid ());
1661 DXunlock(childtbl_lock, 0);
1662
1663 if(_dxd_exMyPID < 0)
1664 _dxf_ExDie("Fork Children unable to get child id %d",
1665 getpid());
1666
1667 #if DXD_EXEC_WAIT_PROCESS
1668 /* The original process (the master) is also the "exParent", and
1669 * can allow the other processes to start now
1670 */
1671 if (_dxd_exMyPID == 0) {
1672 *exReady = TRUE;
1673 exParent = TRUE;
1674 }
1675 #else
1676 *exReady = TRUE;
1677 #endif
1678
1679 #if DXD_HAS_SYSMP
1680
1681 if (nprocs > 1 && nphysprocs == nprocs) {
1682 i = sysmp (MP_MUSTRUN, _dxd_exMyPID % nphysprocs);
1683 if (i < 0) {
1684 char buffer[256];
1685
1686 sprintf(buffer, "%d: MP_MUSTRUN failed", _dxd_exMyPID);
1687 perror(buffer);
1688 }
1689 }
1690 #endif
1691 #if DXD_EXEC_WAIT_PROCESS
1692
1693 } else
1694 _dxd_exMyPID = -1;
1695 #endif
1696 #endif
1697 }
1698
1699 /* return the number of physical processors on the system.
1700 * this is different from the number of processes the user
1701 * asked us to use with -pN
1702 */
_dxfPhysicalProcs()1703 int _dxfPhysicalProcs()
1704 {
1705 return nphysprocs;
1706 }
1707
_dxf_lock_childpidtbl()1708 void _dxf_lock_childpidtbl()
1709 {
1710 DXlock(childtbl_lock, 0);
1711 }
1712
ExReadCharFromRQ_fd(int fd,Pointer p)1713 static int ExReadCharFromRQ_fd (int fd, Pointer p)
1714 {
1715 int ret;
1716 char c;
1717
1718 #if DEBUGMP
1719
1720 if(_dxd_exMyPID == 0)
1721 DXMessage("starting read from rq %d", fd);
1722 #endif
1723
1724 ret = read(fd, &c, 1);
1725 if(ret != 1) {
1726 /*
1727 DXMessage("Error reading from request queue pipe: %d %d", errno, fd);
1728 */
1729 DXRegisterInputHandler(NULL, fd, NULL);
1730 }
1731
1732 #if DEBUGMP
1733 if(_dxd_exMyPID == 0)
1734 DXMessage("-----------finished read from rq");
1735 #endif
1736
1737 return 0;
1738 }
1739
_dxf_update_childpid(int i,int pid,int writefd)1740 void _dxf_update_childpid(int i, int pid, int writefd)
1741 {
1742 /* table should already be locked before this call */
1743
1744 #if DEBUGMP
1745 DXMessage("child %d, writefd %d", i, writefd);
1746 #endif
1747
1748 children[i].pid = pid;
1749 children[i].RQwrite_fd = writefd;
1750 DXunlock(childtbl_lock, 0);
1751 }
1752
_dxf_set_RQ_ReadFromChild1(int readfd)1753 void _dxf_set_RQ_ReadFromChild1(int readfd)
1754 {
1755 exChParent_RQread_fd = readfd;
1756 }
1757
1758 /*
1759 * Set up fd that slaves block on waiting for the master to
1760 * put work in the run queue
1761 */
_dxf_set_RQ_reader(int fd)1762 void _dxf_set_RQ_reader(int fd)
1763 {
1764 exParent_RQread_fd = fd;
1765 DXRegisterInputHandler(ExReadCharFromRQ_fd, fd, NULL);
1766 }
1767
1768 /*
1769 * On slave #1 set up fd for writing to the master
1770 */
1771 void
_dxf_set_RQ_writer(int fd)1772 _dxf_set_RQ_writer(int fd)
1773 {
1774 exParent_RQwrite_fd = fd;
1775 }
1776
_dxf_parent_RQ_message()1777 Error _dxf_parent_RQ_message()
1778 {
1779 int ret;
1780
1781 #if DEBUGMP
1782
1783 DXMessage("writing to parent %d", exParent_RQwrite_fd);
1784 #endif
1785
1786 ret = write(exParent_RQwrite_fd, "a", 1);
1787 if(ret != 1)
1788 _dxf_ExDie("Write Erroring notifying parent of job request, write returns %d, error number %d", ret, errno);
1789 return ERROR;
1790 }
1791
1792 /* Send a message to the child so they know there is work on the queue. */
1793 /* If there is a jobid then only notify the child that the job is for, */
1794 /* otherwise notify all children and the first to get the job wins. */
_dxf_child_RQ_message(int * jobid)1795 Error _dxf_child_RQ_message(int *jobid)
1796 {
1797 int i;
1798 int procid;
1799 int ret;
1800
1801 #if !defined(HAVE__ERRNO)
1802
1803 errno = 0;
1804 #endif
1805
1806 procid = *jobid - 1;
1807
1808 if(procid == 0) {
1809 if(_dxd_exMyPID != 0)
1810 DXWarning("Ignoring rq message to parent");
1811 return ERROR;
1812 }
1813
1814 if(procid > 0) {
1815 #if DEBUGMP
1816 DXMessage("send job request to %d, %d", procid, children[procid].RQwrite_fd);
1817 #endif
1818
1819 ret = write(children[procid].RQwrite_fd, "a", 1);
1820 if(ret != 1)
1821 _dxf_ExDie("Write Erroring notifying child of job request, write returns %d, error number %d", ret, errno);
1822 #if DEBUGMP
1823
1824 else
1825 DXMessage("successful write to %d", children[procid].RQwrite_fd);
1826 #endif
1827
1828 } else { /* if procid == -1 then send message to all children */
1829 for (i = 1; i < nprocs; i++) {
1830 #if DEBUGMP
1831 DXMessage("send job request to %d, %d", i, children[i].RQwrite_fd);
1832 #endif
1833
1834 ret = write(children[i].RQwrite_fd, "a", 1);
1835 if(ret != 1)
1836 _dxf_ExDie("Write Erroring notifying child of job request, write returns %d, error number %d", ret, errno);
1837 #if DEBUGMP
1838
1839 else
1840 DXMessage("successful write to %d", children[i].RQwrite_fd);
1841 #endif
1842
1843 }
1844 }
1845 return ERROR;
1846 }
1847
1848 /*
1849 * Processors are identified by their index into the table of child
1850 * processes.
1851 */
ExFindPID(int pid)1852 static int ExFindPID (int pid)
1853 {
1854 int i;
1855
1856 for (i = 0; i < nprocs; i++)
1857 if (pid == children[i].pid)
1858 return (i);
1859
1860 DXWarning ("#4510", pid);
1861 return (-1);
1862 }
1863
1864
OKToRead(SFILE * fp)1865 static int OKToRead (SFILE *fp)
1866 {
1867 if (ExCheckParseBuffer())
1868 return 1;
1869
1870 return SFILECharReady(fp);
1871 }
1872
_dxf_ExPromptSet(char * var,char * val)1873 void _dxf_ExPromptSet(char *var, char *val)
1874 {
1875 gvar *gv;
1876 String pmpt;
1877
1878 pmpt = DXNewString(val);
1879 gv = _dxf_ExCreateGvar (GV_DEFINED);
1880 _dxf_ExDefineGvar (gv, (Object)pmpt);
1881 _dxf_ExVariableInsert (var, _dxd_exGlobalDict, (EXObj)gv);
1882 }
1883
_dxf_ExPromptGet(char * var)1884 char * _dxf_ExPromptGet(char *var)
1885 {
1886 gvar *gv;
1887 char *val;
1888
1889 if ((gv = (gvar*)_dxf_ExVariableSearch (var, _dxd_exGlobalDict)) == NULL)
1890 return (NULL);
1891 if (DXExtractString((Object)gv->obj, &val) == NULL)
1892 val = NULL;
1893 ExDelete (gv);
1894 return (val);
1895 }
1896
ExFromMasterInputHndlr(int fd,Pointer p)1897 static int ExFromMasterInputHndlr (int fd, Pointer p)
1898 {
1899 Program *graph = NULL;
1900 DistMsg pcktype;
1901 int b, peerwait;
1902 int graphId;
1903 DictType whichdict;
1904 int cacheall, namelen;
1905 char name[1024];
1906 dpversion dpv;
1907
1908 if ((IOCTL(_dxd_exMasterfd, FIONREAD, (char *)&b) < 0) || (b <= 0)) {
1909 printf("Connect to Master closed\n");
1910 ExCleanup();
1911 exit(0);
1912 }
1913
1914 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &pcktype, 1, TYPE_INT,
1915 _dxd_exSwapMsg) < 0) {
1916 DXUIMessage("ERROR", "bad distributed packet type");
1917 ExCleanup();
1918 exit(0);
1919 }
1920
1921 if(pcktype == DPMSG_SIGNATURE || pcktype == DPMSG_SIGNATUREI) {
1922 if(_dxd_exDebug)
1923 printf("signature %x\n", pcktype);
1924 if(pcktype == DPMSG_SIGNATUREI)
1925 _dxd_exSwapMsg = TRUE;
1926 else
1927 _dxd_exSwapMsg = FALSE;
1928 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &pcktype, 1, TYPE_INT,
1929 _dxd_exSwapMsg) < 0) {
1930 DXUIMessage("ERROR", "bad distributed packet type");
1931 ExCleanup();
1932 exit(0);
1933 }
1934 }
1935
1936 if(_dxd_exDebug)
1937 printf("packet type %d\n", pcktype);
1938 else
1939 ExDebug("7", "packet type %d", pcktype);
1940
1941 switch(pcktype) {
1942 case DM_PARSETREE:
1943 _dxd_exParseTree = _dxf_ExReadTree(_dxd_exMasterfd, _dxd_exSwapMsg);
1944 if (_dxd_exParseTree != NULL) {
1945 set_status (PS_GRAPHGEN);
1946 _dxf_ExGraphInit ();
1947 graph = _dxf_ExGraph (_dxd_exParseTree);
1948 if (graph != NULL) {
1949 graph->origin = GO_FOREGROUND;
1950 set_status (PS_GRAPHQUEUE);
1951 #ifdef MAIN_TIMING
1952 DXMarkTimeLocal ("pre gq_enq");
1953 #endif
1954
1955 _dxf_ExGQEnqueue (graph);
1956 }
1957 }
1958 if (_dxd_exParseTree != NULL) {
1959 if (graph == NULL && !_dxd_exRemoteSlave)
1960 _dxf_ExSPack (PACK_COMPLETE, _dxd_exContext->graphId,
1961 "Complete", 8);
1962
1963 _dxf_ExPDestroyNode (_dxd_exParseTree);
1964 }
1965 break;
1966 case DM_INSERTMDICT: {
1967 node *n;
1968 n = _dxf_ExReadTree(_dxd_exMasterfd, _dxd_exSwapMsg);
1969 _dxf_ExMacroInsert (n->v.macro.id->v.id.id, (EXObj) n);
1970 }
1971 break;
1972 case DM_INSERTGDICT:
1973 _dxf_ExRecvGDictPkg(_dxd_exMasterfd, _dxd_exSwapMsg, 0);
1974 break;
1975 case DM_INSERTGDICTNB:
1976 _dxf_ExRecvGDictPkg(_dxd_exMasterfd, _dxd_exSwapMsg, 1);
1977 break;
1978 case DM_EVICTCACHE:
1979 break;
1980 case DM_KILLEXECGRAPH:
1981 *_dxd_exKillGraph = TRUE;
1982 case DM_EXECGRAPH:
1983 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &graphId, 1, TYPE_INT,
1984 _dxd_exSwapMsg) < 0) {
1985 DXUIMessage("ERROR", "bad graph id");
1986 *_dxd_exKillGraph = TRUE;
1987 }
1988 ExCheckGraphQueue(graphId);
1989 ExCheckRunqueue(0);
1990 _dxf_ResumePeers();
1991 break;
1992 case DM_SLISTEN:
1993 _dxf_ExSlaveListen();
1994 break;
1995 case DM_SCONNECT:
1996 _dxf_ExSlaveConnect();
1997 break;
1998 case DM_SLAVEID:
1999 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &_dxd_exSlaveId, 1,
2000 TYPE_INT, _dxd_exSwapMsg) < 0) {
2001 DXUIMessage("ERROR", "bad peer id");
2002 }
2003 ExDebug("7", "My Slave Number is %d", _dxd_exSlaveId);
2004 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &namelen, 1,
2005 TYPE_INT, _dxd_exSwapMsg) < 0) {
2006 DXUIMessage("ERROR", "bad name length for slave hostname");
2007 }
2008 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, _dxd_exHostName, namelen,
2009 TYPE_UBYTE, _dxd_exSwapMsg) < 0) {
2010 DXUIMessage("ERROR", "error receiving slave hostname");
2011 }
2012 break;
2013 case DM_VERSION:
2014 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &dpv.version, 1,
2015 TYPE_INT, _dxd_exSwapMsg) < 0) {
2016 DXUIMessage("ERROR", "bad version number for distributed");
2017 }
2018 ExDebug("7", "DPVERSION is %d", dpv.version);
2019 break;
2020 case DM_FLUSHGLOBAL:
2021 _dxf_ExFlushGlobal();
2022 break;
2023 case DM_FLUSHMACRO:
2024 _dxf_ExFlushMacro();
2025 break;
2026 case DM_FLUSHCACHE:
2027 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &cacheall, 1, TYPE_INT,
2028 _dxd_exSwapMsg) < 0)
2029 DXUIMessage("ERROR", "flush cache: bad parameter");
2030 _dxf_ExCacheFlush(cacheall);
2031 break;
2032 case DM_FLUSHDICT:
2033 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &whichdict, 1,
2034 TYPE_INT, _dxd_exSwapMsg) < 0)
2035 DXUIMessage("ERROR", "bad dictionary type");
2036 switch(whichdict) {
2037 case DICT_GLOBAL:
2038 _dxf_ExDictionaryPurge (_dxd_exGlobalDict);
2039 break;
2040 case DICT_MACRO:
2041 _dxf_ExDictionaryPurge (_dxd_exMacroDict);
2042 break;
2043 case DICT_GRAPH:
2044 _dxf_ExDictionaryPurge (_dxd_exGraphCache);
2045 break;
2046 default:
2047 break;
2048 }
2049 break;
2050 case DM_GRAPHDELETE:
2051 _dxf_SuspendPeers();
2052 _dxf_ExGQDecrement(NULL);
2053 _dxf_ExDistributeMsg(DM_GRAPHDELETECONF, NULL, 0, TOMASTER);
2054 break;
2055 case DM_PERSISTDELETE: {
2056 DelRemote drpkg;
2057
2058 #define GETPER(what, len, whattype) \
2059 if (_dxf_ExReceiveBuffer(_dxd_exMasterfd, what, len, whattype, \
2060 _dxd_exSwapMsg) < 0) \
2061 goto perout_error
2062
2063 GETPER (&drpkg.del_namelen, 1, TYPE_INT);
2064 GETPER (drpkg.del_name, drpkg.del_namelen, TYPE_UBYTE);
2065 GETPER (&drpkg.del_instance, 1, TYPE_INT);
2066
2067 if (_dxf_ExDeleteRemote(drpkg.del_name, drpkg.del_instance) == ERROR)
2068 DXUIMessage("ERROR", "error deleting persistent outboard module");
2069
2070 break;
2071
2072 perout_error:
2073 DXUIMessage("ERROR",
2074 "bad request to delete persistent outboard module");
2075 break;
2076 }
2077 case DM_LOADMDF:
2078 if (_dxf_ExRecvMdfPkg(_dxd_exMasterfd, _dxd_exSwapMsg) == ERROR) {
2079 DXUIMessage("ERROR", "error loading additional mdf entries");
2080 }
2081 break;
2082 case DM_EXIT:
2083 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &peerwait, 1, TYPE_INT,
2084 _dxd_exSwapMsg) < 0) {
2085 DXUIMessage("ERROR", "bad peer wait value for exit");
2086 }
2087 if(peerwait)
2088 _dxf_ExWaitForPeers();
2089 ExCleanup();
2090 exit(0);
2091 case DM_DELETEPEER:
2092 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, &namelen, 1, TYPE_INT,
2093 _dxd_exSwapMsg) < 0) {
2094 DXUIMessage("ERROR", "bad name length for peer name");
2095 }
2096 if(_dxf_ExReceiveBuffer(_dxd_exMasterfd, name, namelen,
2097 TYPE_UBYTE, _dxd_exSwapMsg) < 0) {
2098 DXUIMessage("ERROR", "error receiving peer host name");
2099 }
2100 /* delete peer and close socket */
2101 _dxf_ExDeletePeerByName(name, 1);
2102 break;
2103 default:
2104 DXUIMessage("ERROR", "bad message type %d", pcktype);
2105 ExCleanup();
2106 exit(1);
2107 }
2108 return (0);
2109 }
2110
ExCheckInput()2111 int ExCheckInput ()
2112 {
2113 Program *graph;
2114 static int prompted = FALSE;
2115 char *prompt;
2116 Context savedContext;
2117 extern SFILE *_dxd_exBaseFD;
2118
2119
2120 /* don't read anymore input if we are exiting */
2121 if (*_dxd_exTerminating)
2122 return (0);
2123
2124 _dxf_ExCheckPacket(NULL, 0);
2125
2126 /* If this is the terminal, and the user hasn't typed anything yet,
2127 * prompt him.
2128 */
2129 if ((SFILEisatty(yyin) || (_dxd_exRshInput && yyin == _dxd_exBaseFD)) &&
2130 !prompted && _dxf_ExGQAllDone() && !SFILECharReady(yyin)) {
2131 prompt = _dxf_ExPromptGet(PROMPT_ID_PROMPT);
2132 printf (prompt? prompt: EX_PROMPT);
2133 fflush (stdout);
2134 prompted = TRUE;
2135 }
2136
2137 /* If we have input */
2138 if (OKToRead (yyin)) {
2139 ExDebug ("*1", "input");
2140 prompted = FALSE;
2141 set_status (PS_PARSE);
2142 /* save the values from _dxd_exContext in savedContext */
2143 _dxfCopyContext(&savedContext, _dxd_exContext);
2144 DXqflush ();
2145 _dxf_ExBeginInput ();
2146 yyparse (); /* parse a command */
2147 _dxf_ExEndInput ();
2148 DXqflush ();
2149
2150 /* restore the values in _dxd_exContext from savedContext */
2151 _dxfCopyContext(_dxd_exContext, &savedContext);
2152 graph = NULL;
2153
2154 if (_dxd_exParseTree != NULL) {
2155 set_status (PS_GRAPHGEN);
2156 _dxf_ExGraphInit ();
2157 graph = _dxf_ExGraph (_dxd_exParseTree);
2158 /* we are the master, send a copy of the parse tree
2159 * to all slaves
2160 */
2161 _dxf_ExSendParseTree(_dxd_exParseTree);
2162 if (graph != NULL) {
2163 graph->origin = GO_FOREGROUND;
2164 set_status (PS_GRAPHQUEUE);
2165 #ifdef MAIN_TIMING
2166 DXMarkTimeLocal ("pre gq_enq");
2167 #endif
2168
2169 _dxf_ExGQEnqueue (graph);
2170 }
2171 }
2172
2173 set_status (PS_EXECUTIVE);
2174
2175 /*
2176 * Tell remote that immediate statements are complete and clean
2177 * up the parse tree.
2178 */
2179
2180 if (_dxd_exParseTree != NULL) {
2181 if (graph == NULL)
2182 _dxf_ExSPack (PACK_COMPLETE, _dxd_exContext->graphId, "Complete", 8);
2183
2184 _dxf_ExPDestroyNode (_dxd_exParseTree);
2185 }
2186
2187 #ifdef MAIN_TIMING
2188 DXMarkTimeLocal ("post destro");
2189 #endif
2190
2191 return (1);
2192 }
2193
2194 return (0);
2195 }
2196
2197 /*
2198 * See if there are any tasks ready to be executed.
2199 */
ExCheckRunqueue(int graphId)2200 static int ExCheckRunqueue (int graphId)
2201 {
2202 return (_dxf_ExRQDequeue (0));
2203 }
2204
2205 /*
2206 * See if there is a graph ready for execution
2207 */
ExCheckGraphQueue(int newGraphId)2208 static int ExCheckGraphQueue (int newGraphId)
2209 {
2210 Program *graph;
2211 graph = _dxf_ExGQDequeue ();
2212
2213 if (graph == NULL)
2214 return (FALSE);
2215
2216 #ifdef DXD_LICENSED_VERSION
2217
2218 if (!_dxd_ExHasLicense) {
2219 DXUIMessage("LICENSE","NO LICENSE\n");
2220 return (FALSE);
2221 }
2222
2223 #endif /* DXD_LICENSED VERSION */
2224
2225 if (newGraphId >= 0)
2226 graph->graphId = newGraphId;
2227
2228 _dxd_exContext->graphId = graph->graphId;
2229
2230 /*
2231 * Schedule graph nodes which are ready for execution.
2232 */
2233 #ifdef GQ_TIMING
2234
2235 DXMarkTimeLocal ("pre _dxf_ExQueueGraph");
2236 #endif
2237
2238 set_status (PS_GRAPHQUEUE);
2239 _dxf_ExQueueGraph (graph);
2240 set_status (PS_EXECUTIVE);
2241 #ifdef GQ_TIMING
2242
2243 DXMarkTimeLocal ("post _dxf_ExQueueGraph");
2244 #endif
2245
2246 _dxd_exContext->graphId = 0;
2247
2248 return (TRUE);
2249 }
2250
2251
2252 #define EX_LOOP_TRIES 1000 /* limit sizing iterations */
2253 #define EX_LOOP_PER_SEC 30 /* non-quiescent input check frequency */
2254
2255 #if ibmpvs
2256 #define EX_SELECT 128
2257 #define EX_INCREMENT 0x1
2258 static int EX_LIMIT = 0;
2259 #elif sgi || ibm6000
2260 #define EX_SELECT 16
2261 #define EX_INCREMENT 0x1
2262 #define EX_LIMIT 0x100
2263 #elif solaris
2264 #define EX_SELECT 0
2265 #define EX_INCREMENT 0x1
2266 #define EX_LIMIT 0x100
2267 #else
2268 #define EX_SELECT 1024
2269 #define EX_INCREMENT 0x100
2270 #define EX_LIMIT 0x100000
2271 #endif
2272
2273
ExInputAvailable(SFILE * fp)2274 static int ExInputAvailable (SFILE *fp)
2275 {
2276 static int iters = 0;
2277 extern SFILE *_dxd_exBaseFD;
2278
2279 if (ExCheckParseBuffer())
2280 return TRUE;
2281
2282 _dxf_ExCheckPacket(NULL, 0);
2283
2284 if (SFILECharReady(fp))
2285 return TRUE;
2286
2287 if (fp != _dxd_exBaseFD)
2288 return TRUE;
2289
2290 if (++iters < EX_SELECT) {
2291 int ret, n, fd = SFILEfileno (fp);
2292 ret = IOCTL (fd, FIONREAD, (char *) &n);
2293 return (n > 0 || ret < 0);
2294 } else
2295 return 0;
2296 }
2297
2298
2299 #define ISSUE_PROMPT()\
2300 {\
2301 char *prompt;\
2302 if (! prompted &&\
2303 !SFILECharReady(yyin) &&\
2304 (_dxd_exRshInput || _dxd_exIsatty) &&\
2305 _dxf_ExGQAllDone ())\
2306 {\
2307 prompt = _dxf_ExPromptGet (PROMPT_ID_PROMPT);\
2308 printf (prompt ? prompt : EX_PROMPT);\
2309 fflush (stdout);\
2310 prompted = TRUE;\
2311 }\
2312 }
2313
ExRegisterRQ_fds()2314 static void ExRegisterRQ_fds()
2315 {
2316 DXRegisterInputHandler(ExReadCharFromRQ_fd, exChParent_RQread_fd, NULL);
2317 }
2318
ExParallelMaster()2319 static void ExParallelMaster ()
2320 {
2321 Program *graph;
2322 Context savedContext;
2323 int tries = 0;
2324 int limit = 0;
2325 static int prompted = FALSE;
2326 #if defined(ibmpvs)
2327
2328 int reading = FALSE;
2329 int cnt = 0;
2330 double start = SVS_double_time ();
2331 #else
2332 #define reading TRUE
2333 #endif
2334
2335 _dxd_exParseTree = NULL;
2336
2337 ExRegisterRQ_fds();
2338
2339 for (;;) {
2340 if (++tries > limit) {
2341 /*
2342 * If this is the terminal, and the user hasn't typed anything
2343 * yet then prompt him.
2344 */
2345
2346 ISSUE_PROMPT ();
2347 _dxf_ExCheckRIH();
2348
2349 while (reading && ! *_dxd_exTerminating &&
2350 (ExInputAvailable (yyin) || _dxd_exSelectReturnedInput)
2351 && _dxd_exParseAhead) {
2352 limit = -EX_INCREMENT;
2353
2354 _dxd_exSelectReturnedInput = FALSE;
2355 prompted = FALSE;
2356 set_status (PS_PARSE);
2357 /* save the values from _dxd_exContext in savedContext */
2358 _dxfCopyContext(&savedContext, _dxd_exContext);
2359 _dxf_ExBeginInput ();
2360 if (reading)
2361 yyparse ();
2362 _dxf_ExEndInput ();
2363 /* restore the values in _dxd_exContext from savedContext */
2364 _dxfCopyContext(_dxd_exContext, &savedContext);
2365 if (_dxd_exParseTree) {
2366 set_status (PS_GRAPHGEN);
2367 _dxf_ExGraphInit ();
2368 graph = _dxf_ExGraph (_dxd_exParseTree);
2369 /* we are the master, send a copy of the parse tree
2370 * to all slaves
2371 */
2372 _dxf_ExSendParseTree(_dxd_exParseTree);
2373
2374 if (graph) {
2375 graph->origin = GO_FOREGROUND;
2376 set_status (PS_GRAPHQUEUE);
2377 _dxf_ExGQEnqueue (graph);
2378 ExCheckGraphQueue (-1);
2379 if (_dxf_ExCheckBackground (_dxd_exGlobalDict, TRUE) ||
2380 _dxf_ExCheckVCR (_dxd_exGlobalDict, TRUE))
2381 ExCheckGraphQueue (-1);
2382 } else {
2383 _dxf_ExSPack (PACK_COMPLETE, _dxd_exContext->graphId, "Complete", 8);
2384 }
2385
2386 _dxf_ExPDestroyNode (_dxd_exParseTree);
2387 }
2388
2389 set_status (PS_EXECUTIVE);
2390 }
2391
2392 #if defined(DDX)
2393 {
2394 extern Error SlaveBcastLoop(int, Pointer);
2395 extern int GetMPINodeId();
2396 if (GetMPINodeId() == 0)
2397 _dxf_ExCheckRIHBlock (SFILEfileno (yyin));
2398 else {
2399 SlaveBcastLoop(0, NULL);
2400 _dxf_ExCheckRIH ();
2401 }
2402 }
2403 #endif
2404
2405 limit += EX_INCREMENT;
2406 if (limit > EX_LIMIT)
2407 limit = EX_LIMIT;
2408
2409 tries = 0;
2410 }
2411
2412 if (ExCheckGraphQueue (-1))
2413 continue;
2414
2415 if (_dxf_ExGQAllDone ())
2416 _dxf_RunPendingCmds();
2417
2418 if (_dxf_ExCheckBackground (_dxd_exGlobalDict, TRUE) ||
2419 _dxf_ExCheckVCR (_dxd_exGlobalDict, TRUE)) {
2420 if (ExCheckGraphQueue (-1))
2421 continue;
2422 }
2423
2424 /*
2425 * If we run a job here then we immediately want to check to
2426 * see whether any new input has come in.
2427 */
2428
2429 if (_dxf_ExRQPending () && _dxf_ExRQDequeue (0)) {
2430 #if DEBUGMP
2431 DXMessage("got something");
2432 #endif
2433
2434 tries = limit;
2435 continue;
2436 }
2437
2438 ExCheckTerminate ();
2439
2440 /*
2441 * Since 'os' can't handle blocking reads without blocking the
2442 * entire system, but it can handle blocking selects, we must use
2443 * the later to block on input so that I/O processing destined
2444 * for other processors, specifically that done by RIH (e.g.
2445 * X window expose events, and status window updates, is not also
2446 * blocked.
2447 *
2448 * $$$$$
2449 * For now this seems to make things worse so we'll leave it out.
2450 * $$$$$
2451 */
2452
2453 if (reading && _dxf_ExGQAllDone () && ! _dxf_ExVCRRunning ()) {
2454 ISSUE_PROMPT ();
2455 if (! _dxd_exParseAhead) {
2456 /* if we get here there is nothing in the queues */
2457 /* restore parse ahead in case it was changed */
2458 _dxd_exParseAhead = _dxd_exSParseAhead;
2459 }
2460
2461 #if defined(DDX)
2462 if(!_dxf_ExIsExecuting() && !ExInputAvailable(yyin)) {
2463 extern Error SlaveBcastLoop(int, Pointer);
2464 extern int GetMPINodeId();
2465 if (GetMPINodeId() == 0)
2466 _dxf_ExCheckRIHBlock (SFILEfileno (yyin));
2467 else {
2468 SlaveBcastLoop(0, NULL);
2469 _dxf_ExCheckRIH ();
2470 }
2471 }
2472 #else
2473 #ifndef DXD_NOBLOCK_SELECT
2474 if(!_dxf_ExIsExecuting() && !ExInputAvailable(yyin))
2475 _dxf_ExCheckRIHBlock (SFILEfileno (yyin));
2476 #endif
2477 #endif
2478
2479 }
2480
2481 #if sgi
2482 set_status (PS_NAPPING);
2483 sginap (0);
2484 set_status (PS_EXECUTIVE);
2485 #endif
2486
2487 }
2488 }
2489
2490 #if defined(HAVE_SIGPIPE)
ExSigPipe(int signo)2491 static void ExSigPipe(int signo)
2492 {
2493 /*
2494 * If I am a slave, send a quit signal to the master.
2495 * Otherwise, just quit.
2496 */
2497 if (_dxd_exMyPID < 0 || DXProcessorId() != 0) {
2498 #if 0
2499 fprintf(stderr, "ExSigPipe: slave received %d\n", signo);
2500 #endif
2501 #if HAVE_SIGQUIT
2502
2503 kill(children[0].pid, SIGQUIT);
2504 #endif
2505
2506 } else {
2507 #if 0
2508 fprintf(stderr, "ExSigPipe: master received %d\n", signo);
2509 #endif
2510
2511 ExQuit();
2512 }
2513 }
2514 #endif
2515
2516 #if defined(HAVE_SIGQUIT)
ExSigQuit(int signo)2517 static void ExSigQuit(int signo)
2518 {
2519 /*
2520 * Received by the master from a slave that
2521 * was told to quit, due to either a SIGPIPE
2522 * or SIGDANGER signal. ExQuit will then send
2523 * SIGUSR2 to the children.
2524 */
2525 #if 0
2526 fprintf(stderr, "ExSigQuit: %s receive %d\n",
2527 DXProcessorId() == 0 ? "master" : "slave", signo);
2528 #endif
2529
2530 if (DXProcessorId() == 0)
2531 ExQuit();
2532 else
2533 exit(0);
2534 }
2535 #endif
2536
2537 #if defined(HAVE_SIGDANGER)
ExSigDanger(int signo)2538 static void ExSigDanger (int signo)
2539 {
2540 DXSetError (ERROR_INTERNAL, "#8300");
2541 DXPrintError (NULL);
2542 ExQuit();
2543 exit(1);
2544 }
2545 #endif
2546
2547 #ifdef DXD_WIN
DXWinFork()2548 int DXWinFork()
2549 {
2550 return -1;
2551 }
2552
2553 #endif
2554
2555 #if !defined(intelnt) && !defined(WIN32)
2556
DXForkChild(int i)2557 int DXForkChild(int i)
2558 {
2559 int pid, master2slave[2], slave2master[2];
2560
2561 _dxf_lock_childpidtbl();
2562
2563 /*
2564 * The slaves always need to hear from the master
2565 */
2566 if (pipe(master2slave))
2567 return ERROR;
2568
2569 /*
2570 * The master only needs to hear from slave[1]
2571 */
2572 if (i == 1)
2573 if (pipe(slave2master))
2574 return ERROR;
2575
2576 pid = fork();
2577
2578 /*
2579 * The right thing to do depends on whether we're the parent
2580 * or child process. The parent is always the master, and the
2581 * child is always a slave.
2582 */
2583 if (pid)
2584 {
2585 /*
2586 * The master writes to master2slave[1].
2587 */
2588 close(master2slave[0]);
2589 _dxf_update_childpid(i, pid, master2slave[1]);
2590
2591 /*
2592 * The master only needs to hear from slave[1]
2593 */
2594 if (i == 1)
2595 {
2596 close(slave2master[1]);
2597 _dxf_set_RQ_ReadFromChild1(slave2master[0]);
2598 }
2599 }
2600 else
2601 {
2602 /*
2603 * The child is a slave. It needs to listen to the
2604 * master. Note that the slave2master pipe is only
2605 * required for node 1, and that the master (if we
2606 * forked it at all) should not watch an master2slave
2607 */
2608 close(master2slave[1]);
2609
2610 if (i != 0)
2611 _dxf_set_RQ_reader(master2slave[0]);
2612
2613 if (i == 1)
2614 {
2615 close(slave2master[0]);
2616 _dxf_set_RQ_writer(slave2master[1]);
2617 }
2618 }
2619
2620 return pid;
2621 }
2622 #endif
2623
2624 #if defined(DXD_WIN_SMP) && defined(THIS_IS_COMMENTED)
MyChildProc()2625 static int MyChildProc()
2626 {
2627 int i;
2628 static int iCount = 0;
2629 static __declspec(thread) int tls_td;
2630
2631 iCount++;
2632
2633 tls_td = GetCurrentThreadId();
2634
2635 _dxf_lock_childpidtbl();
2636 _dxf_update_childpid(iCount, tls_td, -1);
2637
2638 i = tls_td;
2639 _dxd_exMyPID = ExFindPID (DXGetPid ());
2640 i = _dxd_exMyPID;
2641
2642 printf("In New child Thread %d \n",tls_td);
2643
2644 ExChildProcess();
2645
2646 /*
2647 _dxf_ExInitTaskPerProc();
2648 ExMainLoopSlave ();
2649 */
2650
2651 printf("End Thread %d \n",tls_td);
2652 return 1;
2653 }
2654
DXWinFork()2655 int DXWinFork()
2656 {
2657 int i;
2658
2659 i = _beginthread(MyChildProc, 0, NULL);
2660 return i;
2661 }
2662
DXGetPid()2663 DXGetPid()
2664 {
2665 int i;
2666 i = GetCurrentThreadId();
2667 return i;
2668 }
2669
2670
2671 #endif
2672
2673
2674