*** empty log message ***
[dyninst.git] / paradyn / src / pdMain / main.C
1 /*
2  * Copyright (c) 1996-1999 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 // $Id: main.C,v 1.50 1999/03/03 18:17:02 pcroth Exp $
43
44 /*
45  * main.C - main routine for paradyn.  
46  *   This routine creates DM, UIM, VM, and PC threads.
47  */
48
49 #include "../TCthread/tunableConst.h"
50 #include "util/h/headers.h"
51 #include "paradyn.h"
52 #include "thread/h/thread.h"
53 #include "dataManager.thread.SRVR.h"
54 #include "VM.thread.SRVR.h"
55 #include "../UIthread/tkTools.h" // tclpanic
56 #include "util/h/makenan.h"
57 #include "paradyn/src/DMthread/BufferPool.h"
58 #include "paradyn/src/DMthread/DVbufferpool.h"
59
60 #include "tcl.h"
61 #include "tk.h"
62
63
64 // trace data streams
65 BufferPool<traceDataValueType>  tracedatavalues_bufferpool;
66
67 // maybe this should be a thread, but for now it's a global var.
68 BufferPool<dataValueType>  datavalues_bufferpool;
69
70
71 extern void *UImain(void *);
72 extern void *DMmain(void *);
73 extern void *PCmain(void *);
74 extern void *VMmain (void *);
75
76 #define MBUFSIZE 256
77 #define DEBUGBUFSIZE    4096
78
79 thread_t UIMtid;
80 thread_t MAINtid;
81 thread_t PCtid;
82 thread_t DMtid;
83 thread_t VMtid;
84 //thread_t TCtid; // tunable constants
85
86 // expanded stack by a factor of 10 to support AIX - jkh 8/14/95
87 // wrapped it in an ifdef so others don't pay the price --ari 10/95
88 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
89 char UIStack[327680];
90 char DMStack[327680];
91 #else
92 char UIStack[32768];
93 char DMStack[32768];
94 #endif
95
96
97 // applicationContext *context;
98 dataManagerUser *dataMgr;
99 performanceConsultantUser *perfConsult;
100 UIMUser *uiMgr;
101 VMUser  *vmMgr;
102 int paradyn_debug=0;
103 char debug_buf[DEBUGBUFSIZE];
104
105 // default_host defines the host where programs run when no host is
106 // specified in a PCL process definition, or in the process definition window.
107 string default_host;
108
109
110 #define PRINT_DEBUG_MACRO                               \
111 do {                                                    \
112         va_list args;                                   \
113         va_start(args,format);                          \
114         (void) fflush(stdout);                          \
115         (void) vsprintf(debug_buf, format, args);       \
116         (void) fprintf(stdout,"THREAD %d: %s\n",        \
117                thr_self(), debug_buf);                  \
118         (void) fflush(stdout);                          \
119         va_end(args);                                   \
120 } while (0)
121
122 void print_debug_macro(const char* format, ...){
123   if(paradyn_debug > 0)
124      PRINT_DEBUG_MACRO;
125   return;
126 }
127
128 void eFunction(int errno, char *message)
129 {
130     printf("error #%d: %s\b", errno, message);
131     abort();
132 }
133
134 //extern bool metMain(string&);
135 extern bool metDoTunable();
136 extern bool metDoProcess();
137 extern bool metDoDaemon();
138
139 Tcl_Interp *interp;
140 int         tty;
141
142 bool inDeveloperMode = false; // global variable used elsewhere
143 void develModeCallback(bool newValue) {
144    inDeveloperMode = newValue;
145
146    // plus any other necessary action...
147    // The shg wants to hear of such changes, so it can resize its
148    // status line (w/in the shg window) appropriately
149    extern void shgDevelModeChange(Tcl_Interp *, bool);
150    shgDevelModeChange(interp, inDeveloperMode);
151 }
152
153 int
154 main (int argc, char **argv)
155 {
156   char mbuf[MBUFSIZE];
157   unsigned int msgsize;
158   thread_t mtid;
159   tag_t mtag;
160   char *temp=NULL;
161
162   // Initialize tcl/tk
163   interp = Tcl_CreateInterp();
164   assert(interp);
165
166   tty = isatty(0);
167   Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
168
169   if (Tcl_Init(interp) == TCL_ERROR)
170      tclpanic(interp, "tcl_init() failed (perhaps TCL_LIBRARY not set?)");
171   if (Tk_Init(interp) == TCL_ERROR)
172      tclpanic(interp, "tk_init() failed (perhaps TK_LIBRARY not set?)");
173 //  if (Tix_Init(interp) == TCL_ERROR)
174 //     tclpanic(interp, "tix_init() failed (perhaps TIX_LIBRARY not set?");
175
176   // copy command-line arguments into tcl vrbles argc / argv
177   char *args = Tcl_Merge(argc - 1, (char **) (argv + 1));
178   Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
179   Tcl_Free(args);
180
181   string argcStr = string(argc - 1);
182   Tcl_SetVar(interp, "argc", (char*)argcStr.string_of(), TCL_GLOBAL_ONLY);
183   Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY);
184
185   // Here is one tunable constant that is definitely intended to be hard-coded in:
186    tunableBooleanConstantDeclarator tcInDeveloperMode("developerMode",
187          "Allow access to all tunable constants, including those limited to developer mode.  (Use with caution)",
188          false, // initial value
189          develModeCallback,
190          userConstant);
191
192     tunableConstantRegistry::createFloatTunableConstant
193     ("EnableRequestPacketSize",
194      "Enable request packet size",
195      NULL,
196      developerConstant,
197      10.0, // initial value
198      1.0,  // min
199      100.0); // max
200
201   //
202   // We check our own read/write events.
203   //
204 #if !defined(i386_unknown_nt4_0)
205   P_signal(SIGPIPE, (P_sig_handler) SIG_IGN);
206 #endif // !defined(i386_unknown_nt4_0)
207
208   // get paradyn_debug environment var PARADYNDEBUG, if its value
209   // is > 1, then PARADYN_DEBUG msgs will be printed to stdout
210   temp = (char *) getenv("PARADYNDEBUG");
211   if (temp != NULL) {
212     paradyn_debug = atoi(temp);
213   }
214   else {
215     paradyn_debug = 0;
216   }
217
218 // parse the command line arguments
219   int a_ct=1;
220   char *fname=0, *sname=0, *xname=0;
221   while (argv[a_ct]) {
222     if (fname == 0 && !strcmp(argv[a_ct], "-f") && argv[a_ct+1]) {
223       fname = argv[++a_ct];
224     } else if (sname == 0 && !strcmp(argv[a_ct], "-s") && argv[a_ct+1]) {
225       sname = argv[++a_ct];
226     } else if (xname == 0 && !strcmp(argv[a_ct], "-x") && argv[a_ct+1]) {
227       xname = argv[++a_ct];
228     } else if (!default_host.length() && (!strcmp(argv[a_ct], "-default_host") || !strcmp(argv[a_ct], "-d")) && argv[a_ct+1]) {
229       default_host = argv[++a_ct];
230     } else {
231       printf("usage: %s [-f <pcl_filename>] [-s <tcl_scriptname>]"
232                       " [-x <connect_filename>] [-default_host <hostname>]\n",
233                  argv[0]);
234       exit(-1);
235     }
236     a_ct++;
237   }
238
239   // initialize default host here, if it was not defined in a command line argument
240   if (!default_host.length()) {
241     default_host = getHostName();
242   }
243
244 // get tid of parent
245   MAINtid = thr_self();
246
247 // Structure used to pass initial arguments to data manager
248 //  init_struct init; init.tid = MAINtid; init.met_file = fname;
249
250 // call sequential initialization routines
251   if(!dataManager::DM_sequential_init(fname)) {
252     printf("Error found in Paradyn Configuration File, exiting\n");
253     exit(-1);
254   }
255   VM::VM_sequential_init(); 
256
257
258      /* initialize the 4 main threads of paradyn: data manager, visi manager,
259         user interface manager, performance consultant */
260   
261 // initialize DM
262
263   if (thr_create(DMStack, sizeof(DMStack), DMmain, (void *) &MAINtid, 0, 
264                  (unsigned int *) &DMtid) == THR_ERR)
265     exit(1);
266   PARADYN_DEBUG (("DM thread created\n"));
267
268   msgsize = MBUFSIZE;
269   mtid = THR_TID_UNSPEC;
270   mtag = MSG_TAG_DM_READY;
271   msg_recv(&mtid, &mtag, mbuf, &msgsize);
272   assert( mtid == DMtid );
273   msg_send (DMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
274   dataMgr = new dataManagerUser (DMtid);
275   // context = dataMgr->createApplicationContext(eFunction);
276
277 // initialize UIM 
278  
279   if (thr_create (UIStack, sizeof(UIStack), &UImain, NULL,
280                   0, &UIMtid) == THR_ERR) 
281     exit(1);
282   PARADYN_DEBUG (("UI thread created\n"));
283
284   msgsize = MBUFSIZE;
285   mtid = THR_TID_UNSPEC;
286   mtag = MSG_TAG_UIM_READY;
287   msg_recv(&mtid, &mtag, mbuf, &msgsize);
288   assert( mtid == UIMtid );
289   msg_send (UIMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
290   uiMgr = new UIMUser (UIMtid);
291
292 // initialize PC
293
294   if (thr_create(0, 0, PCmain, (void*) &MAINtid, 0, 
295                  (unsigned int *) &PCtid) == THR_ERR)
296     exit(1);
297   PARADYN_DEBUG (("PC thread created\n"));
298
299   msgsize = MBUFSIZE;
300   mtid = THR_TID_UNSPEC;
301   mtag = MSG_TAG_PC_READY;
302   msg_recv(&mtid, &mtag, mbuf, &msgsize);
303   assert( mtid == PCtid );
304   msg_send (PCtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
305   perfConsult = new performanceConsultantUser (PCtid);
306
307 // initialize VM
308   if (thr_create(0, 0, VMmain, (void *) &MAINtid, 0, 
309                  (unsigned int *) &VMtid) == THR_ERR)
310     exit(1);
311
312   PARADYN_DEBUG (("VM thread created\n"));
313   msgsize = MBUFSIZE;
314   mtid = THR_TID_UNSPEC;
315   mtag = MSG_TAG_VM_READY;
316   msg_recv(&mtid, &mtag, mbuf, &msgsize);
317   assert( mtid == VMtid );
318   msg_send (VMtid, MSG_TAG_ALL_CHILDREN_READY, (char *) NULL, 0);
319   vmMgr = new VMUser (VMtid);
320
321   // execute the commands in the configuration files
322   metDoTunable();
323   metDoDaemon();
324   metDoProcess();
325
326   // keep this here to prevent UI from starting up till everything's 
327   // been initialized properly!!
328   //  -OR-
329   // move this elsewhere to create a race condition
330   if (sname)
331     uiMgr->readStartupFile (sname);
332  
333   if (xname)
334     dataMgr->printDaemonStartInfo (xname);
335
336 // wait for UIM thread to exit 
337
338   thr_join (UIMtid, NULL, NULL);
339
340   Tcl_DeleteInterp(interp);
341
342   return 0;
343 }