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