Added "-x <connect_file>" option for remote/manual paradynd start-up
[dyninst.git] / paradyn / src / pdMain / main.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /* $Log: main.C,v $
43 /* Revision 1.48  1998/03/03 23:35:00  wylie
44 /* Added "-x <connect_file>" option for remote/manual paradynd start-up
45 /* (aka "Globus" support).
46 /*
47  * Revision 1.47  1997/04/21 16:55:52  hseom
48  * added support for trace data
49  *
50  * Revision 1.46  1996/11/26 16:07:20  naim
51  * Fixing asserts - naim
52  *
53  * Revision 1.45  1996/08/16 21:13:02  tamches
54  * updated copyright for release 1.1
55  *
56  * Revision 1.44  1996/08/05 07:33:03  tamches
57  * update for tcl 7.5
58  *
59  * Revision 1.43  1996/05/30 21:56:50  tamches
60  * made UIStack bigger for aix 4.1 too (had been just 3.2)
61  *
62  * Revision 1.42  1996/05/06 17:13:39  newhall
63  * changed initial value of EnableRequestPacketSize tunable constant from 2 to 10
64  *
65  * Revision 1.41  1996/04/05  21:02:39  naim
66  * Chaging default value for packet size tunable constant - naim
67  *
68  * Revision 1.40  1996/03/14  14:22:42  naim
69  * Batching enable data requests for better performance - naim
70  *
71  * Revision 1.39  1996/02/02  02:08:20  karavan
72  * moved performance consultant related tunable constant definitions to the
73  * PC thread.
74  *
75  * Revision 1.38  1996/01/29 22:12:59  mjrg
76  * Added metric propagation when new processes start
77  * Adjust time to account for clock differences between machines
78  * Daemons don't enable internal metrics when they are not running any processes
79  * Changed CM5 start (paradynd doesn't stop application at first breakpoint;
80  * the application stops only after it starts the CM5 daemon)
81  * Added -default_host option to paradyn
82  *
83  */
84
85 /*
86  * main.C - main routine for paradyn.  
87  *   This routine creates DM, UIM, VM, and PC threads.
88  */
89
90 #include "tcl.h"
91 #include "tk.h"
92
93 #include "../TCthread/tunableConst.h"
94 #include "util/h/headers.h"
95 #include "paradyn.h"
96 #include "thread/h/thread.h"
97 #include "dataManager.thread.SRVR.h"
98 #include "VM.thread.SRVR.h"
99 #include "../UIthread/tkTools.h" // tclpanic
100 #include "util/h/makenan.h"
101 #include "paradyn/src/DMthread/BufferPool.h"
102 #include "paradyn/src/DMthread/DVbufferpool.h"
103
104 // trace data streams
105 BufferPool<traceDataValueType>  tracedatavalues_bufferpool;
106
107 // maybe this should be a thread, but for now it's a global var.
108 BufferPool<dataValueType>  datavalues_bufferpool;
109
110
111 extern void *UImain(void *);
112 extern void *DMmain(void *);
113 extern void *PCmain(void *);
114 extern void *VMmain (void *);
115
116 #define MBUFSIZE 256
117 #define DEBUGBUFSIZE    4096
118
119 thread_t UIMtid;
120 thread_t MAINtid;
121 thread_t PCtid;
122 thread_t DMtid;
123 thread_t VMtid;
124 //thread_t TCtid; // tunable constants
125
126 // expanded stack by a factor of 10 to support AIX - jkh 8/14/95
127 // wrapped it in an ifdef so others don't pay the price --ari 10/95
128 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
129 char UIStack[327680];
130 #else
131 char UIStack[32768];
132 #endif
133
134 // applicationContext *context;
135 dataManagerUser *dataMgr;
136 performanceConsultantUser *perfConsult;
137 UIMUser *uiMgr;
138 VMUser  *vmMgr;
139 int paradyn_debug=0;
140 char debug_buf[DEBUGBUFSIZE];
141
142 // default_host defines the host where programs run when no host is
143 // specified in a PCL process definition, or in the process definition window.
144 string default_host;
145
146
147 #define PRINT_DEBUG_MACRO                               \
148 do {                                                    \
149         va_list args;                                   \
150         va_start(args,format);                          \
151         (void) fflush(stdout);                          \
152         (void) vsprintf(debug_buf, format, args);       \
153         (void) fprintf(stdout,"THREAD %d: %s\n",        \
154                thr_self(), debug_buf);                  \
155         (void) fflush(stdout);                          \
156         va_end(args);                                   \
157 } while (0)
158
159 void print_debug_macro(const char* format, ...){
160   if(paradyn_debug > 0)
161      PRINT_DEBUG_MACRO;
162   return;
163 }
164
165 void eFunction(int errno, char *message)
166 {
167     printf("error #%d: %s\b", errno, message);
168     abort();
169 }
170
171 extern bool metDoTunable();
172 extern bool metDoProcess();
173 extern bool metMain(string&);
174 extern bool metDoProcess();
175 extern bool metDoDaemon();
176
177 Tcl_Interp *interp;
178 int         tty;
179
180 bool inDeveloperMode = false; // global variable used elsewhere
181 void develModeCallback(bool newValue) {
182    inDeveloperMode = newValue;
183
184    // plus any other necessary action...
185    // The shg wants to hear of such changes, so it can resize its
186    // status line (w/in the shg window) appropriately
187    extern void shgDevelModeChange(Tcl_Interp *, bool);
188    shgDevelModeChange(interp, inDeveloperMode);
189 }
190
191 int
192 main (int argc, char **argv)
193 {
194   char mbuf[MBUFSIZE];
195   unsigned int msgsize;
196   tag_t mtag;
197   char *temp=NULL;
198
199   // Initialize tcl/tk
200   interp = Tcl_CreateInterp();
201   assert(interp);
202
203   tty = isatty(0);
204   Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
205
206   if (Tcl_Init(interp) == TCL_ERROR)
207      tclpanic(interp, "tcl_init() failed (perhaps TCL_LIBRARY not set?)");
208   if (Tk_Init(interp) == TCL_ERROR)
209      tclpanic(interp, "tk_init() failed (perhaps TK_LIBRARY not set?)");
210 //  if (Tix_Init(interp) == TCL_ERROR)
211 //     tclpanic(interp, "tix_init() failed (perhaps TIX_LIBRARY not set?");
212
213   // copy command-line arguments into tcl vrbles argc / argv
214   char *args = Tcl_Merge(argc - 1, (const char **) (argv + 1));
215   Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
216   ckfree(args);
217
218   string argcStr = string(argc - 1);
219   Tcl_SetVar(interp, "argc", argcStr.string_of(), TCL_GLOBAL_ONLY);
220   Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY);
221
222   // Here is one tunable constant that is definitely intended to be hard-coded in:
223    tunableBooleanConstantDeclarator tcInDeveloperMode("developerMode",
224          "Allow access to all tunable constants, including those limited to developer mode.  (Use with caution)",
225          false, // initial value
226          develModeCallback,
227          userConstant);
228
229     tunableConstantRegistry::createFloatTunableConstant
230     ("EnableRequestPacketSize",
231      "Enable request packet size",
232      NULL,
233      developerConstant,
234      10.0, // initial value
235      1.0,  // min
236      100.0); // max
237
238   //
239   // We check our own read/write events.
240   //
241   P_signal(SIGPIPE, (P_sig_handler) SIG_IGN);
242
243   // get paradyn_debug environment var PARADYNDEBUG, if its value
244   // is > 1, then PARADYN_DEBUG msgs will be printed to stdout
245   temp = (char *) getenv("PARADYNDEBUG");
246   if (temp != NULL) {
247     paradyn_debug = atoi(temp);
248   }
249   else {
250     paradyn_debug = 0;
251   }
252
253 // parse the command line arguments
254   int a_ct=1;
255   char *fname=0, *sname=0, *xname=0;
256   while (argv[a_ct]) {
257     if (fname == 0 && !strcmp(argv[a_ct], "-f") && argv[a_ct+1]) {
258       fname = argv[++a_ct];
259     } else if (sname == 0 && !strcmp(argv[a_ct], "-s") && argv[a_ct+1]) {
260       sname = argv[++a_ct];
261     } else if (xname == 0 && !strcmp(argv[a_ct], "-x") && argv[a_ct+1]) {
262       xname = argv[++a_ct];
263     } else if (!default_host.length() && (!strcmp(argv[a_ct], "-default_host") || !strcmp(argv[a_ct], "-d")) && argv[a_ct+1]) {
264       default_host = argv[++a_ct];
265     } else {
266       printf("usage: %s [-f <pcl_filename>] [-s <tcl_scriptname>]"
267                       " [-x <connect_filename>] [-default_host <hostname>]\n",
268                  argv[0]);
269       exit(-1);
270     }
271     a_ct++;
272   }
273
274   // initialize default host here, if it was not defined in a command line argument
275   if (!default_host.length()) {
276     struct utsname un;
277     P_uname(&un);
278     default_host = un.nodename;
279   }
280
281 // get tid of parent
282   MAINtid = thr_self();
283
284 // Structure used to pass initial arguments to data manager
285 //  init_struct init; init.tid = MAINtid; init.met_file = fname;
286
287 // call sequential initialization routines
288   if(!dataManager::DM_sequential_init(fname)) {
289     printf("Error found in Paradyn Configuration File, exiting\n");
290     exit(-1);
291   }
292   VM::VM_sequential_init(); 
293
294
295      /* initialize the 4 main threads of paradyn: data manager, visi manager,
296         user interface manager, performance consultant */
297   
298 // initialize DM
299
300   if (thr_create(0, 0, DMmain, (void *) &MAINtid, 0, 
301                  (unsigned int *) &DMtid) == THR_ERR)
302     exit(1);
303   PARADYN_DEBUG (("DM thread created\n"));
304
305   msgsize = MBUFSIZE;
306   mtag = MSG_TAG_DM_READY;
307   msg_recv(&mtag, mbuf, &msgsize);
308   msg_send (DMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
309   dataMgr = new dataManagerUser (DMtid);
310   // context = dataMgr->createApplicationContext(eFunction);
311
312 // initialize UIM 
313  
314   if (thr_create (UIStack, sizeof(UIStack), &UImain, NULL,
315                   0, &UIMtid) == THR_ERR) 
316     exit(1);
317   PARADYN_DEBUG (("UI thread created\n"));
318
319   msgsize = MBUFSIZE;
320   mtag = MSG_TAG_UIM_READY;
321   msg_recv(&mtag, mbuf, &msgsize);
322   msg_send (UIMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
323   uiMgr = new UIMUser (UIMtid);
324
325 // initialize PC
326
327   if (thr_create(0, 0, PCmain, (void*) &MAINtid, 0, 
328                  (unsigned int *) &PCtid) == THR_ERR)
329     exit(1);
330   PARADYN_DEBUG (("PC thread created\n"));
331
332   msgsize = MBUFSIZE;
333   mtag = MSG_TAG_PC_READY;
334   msg_recv(&mtag, mbuf, &msgsize);
335   msg_send (PCtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
336   perfConsult = new performanceConsultantUser (PCtid);
337
338 // initialize VM
339   if (thr_create(0, 0, VMmain, (void *) &MAINtid, 0, 
340                  (unsigned int *) &VMtid) == THR_ERR)
341     exit(1);
342
343   PARADYN_DEBUG (("VM thread created\n"));
344   msgsize = MBUFSIZE;
345   mtag = MSG_TAG_VM_READY;
346   msg_recv(&mtag, mbuf, &msgsize);
347   msg_send (VMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
348   vmMgr = new VMUser (VMtid);
349
350   // execute the commands in the configuration files
351   metDoTunable();
352   metDoDaemon();
353   metDoProcess();
354
355   // keep this here to prevent UI from starting up till everything's 
356   // been initialized properly!!
357   //  -OR-
358   // move this elsewhere to create a race condition
359   if (sname)
360     uiMgr->readStartupFile (sname);
361  
362   if (xname)
363     dataMgr->printDaemonStartInfo (xname);
364
365 // wait for UIM thread to exit 
366
367   thr_join (UIMtid, NULL, NULL);
368
369   Tcl_DeleteInterp(interp);
370 }