Merge branch 'charm' into development
[charm.git] / src / ck-core / init.C
1 /**
2 \addtogroup CkInit
3 \brief Controls the Charm++ startup process.
4
5 This file runs the entire Charm++ startup process.
6
7 The process begins with every processor finishing the 
8 Converse startup process and calling _initCharm.
9 This routine runs almost the entire Charm++ setup process.
10 It begins by setting up various Cpvs and subsystems.
11
12 The rank 0 processor of each node then does
13 the Charm++ registration, by calling the various _register
14 routines.  
15
16 Now processor 0:
17 <ol>
18 <li>Creates each mainchare, by allocating the chares
19  and calling their constructors with argc/argv.
20  This typically results in a number of chare/group creations.
21 <li>Sends off all readonly data to the other processors.
22 </ol>
23 After _initCharm, processor 0 immediately begins work.
24
25 The other processors, however, must wait until they recieve 
26 the readonly data and all group creations.  They do this by 
27 setting the _charmHandlerIdx to a special "_bufferHandler"
28 which simply saves all normal messages into a special queue.  
29
30 As the startup data (readonlies and group creations) streams
31 into _initHandler, it counts messages until it is fully 
32 initialized, then calls _initDone to clean out the queues 
33 and resume normal operation.  
34
35 Upon resume of normal operation, the user code is guaranteed that
36 all readonlies (both data and messages) have been set consistently
37 on all processors, and that the constructors for all nodegroups
38 and groups allocated from a mainchare have been called.
39
40 It is not guaranteed the order in which (node)groups allocated
41 outside of a mainchare are constructed, nor that the construction
42 will happen before other messages have been delivered by the scheduler.
43
44 Even though not exposed to the final users, the creation order of
45 groups and nodegroups allocated in mainchares is deterministic and
46 respects the following points:
47 <ul>
48 <li>On all processors, there is no guarantee of the order of creation
49 between (node)groups allocated from different mainchares;
50 <li>On processor zero, within a mainchare, all (node)groups are created
51 in the order specified by the source code (strictly), including array
52 allocation of initial elements;
53 <li>On processors other than zero, within a mainchare, the order
54 specified by the source code is maintained between different nodegroups
55 and between different groups;
56 <li>On processors other than zero, the ordering between groups and
57 nodegroups is NOT maintained, as all nodegroups are created before any
58 group is created.
59 </ul>
60
61 This process should not have race conditions, but it can
62 never be excluded...
63 */
64 /*@{*/
65
66 #include "ck.h"
67 #include "trace.h"
68
69 void CkRestartMain(const char* dirname);
70
71 #define  DEBUGF(x)     //CmiPrintf x;
72
73 #ifdef CALCULATE_HOPS
74 /** Turn on manually if you want to calculate hops from within Charm++
75 for some application **/
76
77 #include "TopoManager.h"
78
79 TopoManager *tmgr = NULL;
80 double hops = 0;
81
82 extern "C" void calculateTotalHops(int pe1, int pe2, int size) {
83   if(tmgr == NULL)
84     tmgr = new TopoManager();
85   hops += (tmgr->getHopsBetweenRanks(pe1, pe2) * size);
86 }
87
88 extern "C" void printTotalHops() {
89   CmiPrintf("TOTAL HOPS %lf\n", hops/(1024*1024) );
90 }
91 #endif
92
93 UChar _defaultQueueing = CK_QUEUEING_FIFO;
94
95 UInt  _printCS = 0;
96 UInt  _printSS = 0;
97
98 /**
99  * This value has the number of total initialization message a processor awaits.
100  * It is received on nodes other than zero together with the ROData message.
101  * Even though it is shared by all processors it is ok: it doesn't matter when and
102  * by who it is set, provided that it becomes equal to the number of awaited messages
103  * (which is always at least one ---the readonly data message).
104  */
105 UInt  _numExpectInitMsgs = 0;
106 /**
107  * This number is used only by processor zero to count how many messages it will
108  * send out for the initialization process. After the readonly data message is sent
109  * (containing this counter), its value becomes irrelevant.
110  */
111 UInt  _numInitMsgs = 0;
112 /**
113  * Count the number of nodegroups that have been created in mainchares.
114  * Since the nodegroup creation is executed by a single processor in a
115  * given node, this value must be seen by all processors in a node.
116  */
117 CksvDeclare(UInt,_numInitNodeMsgs);
118 int   _infoIdx;
119 int   _charmHandlerIdx;
120 int   _initHandlerIdx;
121 int   _roRestartHandlerIdx;
122 int   _bocHandlerIdx;
123 int   _qdHandlerIdx;
124 int   _qdCommHandlerIdx;
125 int   _triggerHandlerIdx;
126 int   _mainDone = 0;
127 static int   _triggersSent = 0;
128
129 CkOutStream ckout;
130 CkErrStream ckerr;
131 CkInStream  ckin;
132
133 CkpvDeclare(void*,       _currentChare);
134 CkpvDeclare(int,         _currentChareType);
135 CkpvDeclare(CkGroupID,   _currentGroup);
136 CkpvDeclare(void*,       _currentNodeGroupObj);
137 CkpvDeclare(CkGroupID,   _currentGroupRednMgr);
138 CkpvDeclare(GroupTable*, _groupTable);
139 CkpvDeclare(GroupIDTable*, _groupIDTable);
140 CkpvDeclare(CmiImmediateLockType, _groupTableImmLock);
141 CkpvDeclare(UInt, _numGroups);
142
143 CkpvDeclare(CkCoreState *, _coreState);
144
145 CksvDeclare(UInt, _numNodeGroups);
146 CksvDeclare(GroupTable*, _nodeGroupTable);
147 CksvDeclare(GroupIDTable, _nodeGroupIDTable);
148 CksvDeclare(CmiImmediateLockType, _nodeGroupTableImmLock);
149 CksvDeclare(CmiNodeLock, _nodeLock);
150 CksvStaticDeclare(PtrVec*,_nodeBocInitVec);
151 CkpvDeclare(int, _charmEpoch);
152
153 CkpvDeclare(Stats*, _myStats);
154 CkpvDeclare(MsgPool*, _msgPool);
155
156 CkpvDeclare(_CkOutStream*, _ckout);
157 CkpvDeclare(_CkErrStream*, _ckerr);
158
159 CkpvStaticDeclare(int,  _numInitsRecd);
160 CkpvStaticDeclare(PtrQ*, _buffQ);
161 CkpvStaticDeclare(PtrVec*, _bocInitVec);
162
163 #ifndef CMK_CHARE_USE_PTR
164 CpvExtern(CkVec<void *>, chare_objs);
165 CpvExtern(CkVec<int>, chare_types);
166 CpvExtern(CkVec<VidBlock *>, vidblocks);
167 #endif
168
169 /*
170         FAULT_EVAC
171 */
172 CpvDeclare(char *, _validProcessors);
173 CpvDeclare(char ,startedEvac);
174
175 int    _exitHandlerIdx;
176
177 static Stats** _allStats = 0;
178
179 static int   _numStatsRecd = 0;
180 static int   _exitStarted = 0;
181
182 static InitCallTable _initCallTable;
183
184 #ifndef CMK_OPTIMIZE
185 #define _STATS_ON(x) (x) = 1
186 #else
187 #define _STATS_ON(x) \
188           CmiPrintf("stats unavailable in optimized version. ignoring...\n");
189 #endif
190
191 // fault tolerance
192 typedef void (*CkFtFn)(const char *, CkArgMsg *);
193 static CkFtFn  faultFunc = NULL;
194 static char* _restartDir;
195
196 #ifdef _FAULT_MLOG_
197 int chkptPeriod=1000;
198 bool parallelRestart=false;
199 extern int BUFFER_TIME; //time spent waiting for buffered messages
200 #endif
201
202 // flag for killing processes 
203 extern int killFlag;
204 // file specifying the processes to be killed
205 extern char *killFile;
206 // function for reading the kill file
207 void readKillFile();
208
209
210 int _defaultObjectQ = 0;            // for obejct queue
211 int _ringexit = 0;                  // for charm exit
212 int _ringtoken = 8;
213
214
215 /*
216         FAULT_EVAC
217
218         flag which marks whether or not to trigger the processor shutdowns
219 */
220 static int _raiseEvac=0;
221 static char *_raiseEvacFile;
222 void processRaiseEvacFile(char *raiseEvacFile);
223
224 static inline void _parseCommandLineOpts(char **argv)
225 {
226   if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
227       _STATS_ON(_printCS);
228   if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
229       _STATS_ON(_printSS);
230   if (CmiGetArgFlagDesc(argv,"+fifo", "Default to FIFO queuing"))
231       _defaultQueueing = CK_QUEUEING_FIFO;
232   if (CmiGetArgFlagDesc(argv,"+lifo", "Default to LIFO queuing"))
233       _defaultQueueing = CK_QUEUEING_LIFO;
234   if (CmiGetArgFlagDesc(argv,"+ififo", "Default to integer-prioritized FIFO queuing"))
235       _defaultQueueing = CK_QUEUEING_IFIFO;
236   if (CmiGetArgFlagDesc(argv,"+ilifo", "Default to integer-prioritized LIFO queuing"))
237       _defaultQueueing = CK_QUEUEING_ILIFO;
238   if (CmiGetArgFlagDesc(argv,"+bfifo", "Default to bitvector-prioritized FIFO queuing"))
239       _defaultQueueing = CK_QUEUEING_BFIFO;
240   if (CmiGetArgFlagDesc(argv,"+blifo", "Default to bitvector-prioritized LIFO queuing"))
241       _defaultQueueing = CK_QUEUEING_BLIFO;
242   if (CmiGetArgFlagDesc(argv,"+objq", "Default to use object queue for every obejct"))
243   {
244 #if CMK_OBJECT_QUEUE_AVAILABLE
245       _defaultObjectQ = 1;
246       if (CkMyPe()==0)
247         CmiPrintf("Charm++> Create object queue for every Charm object.\n");
248 #else
249       CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
250 #endif
251   }
252   if(CmiGetArgString(argv,"+restart",&_restartDir))
253       faultFunc = CkRestartMain;
254 #if __FAULT__
255   if (CmiGetArgFlagDesc(argv,"+restartaftercrash","restarting this processor after a crash")){  
256 # if CMK_MEM_CHECKPOINT
257       faultFunc = CkMemRestart;
258 # endif
259 #ifdef _FAULT_MLOG_
260             faultFunc = CkMlogRestart;
261 #endif
262       CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
263   }
264   // reading the killFile
265   if(CmiGetArgStringDesc(argv,"+killFile", &killFile,"Generates SIGKILL on specified processors")){
266     if(faultFunc == NULL){
267       //do not read the killfile if this is a restarting processor
268       killFlag = 1;
269       if(CmiMyPe() == 0){
270         printf("[%d] killFlag set to 1 for file %s\n",CkMyPe(),killFile);
271       }
272     }
273   }
274 #endif
275
276   // shut down program in ring fashion to allow projections output w/o IO error
277   if (CmiGetArgIntDesc(argv,"+ringexit",&_ringtoken, "Program exits in a ring fashion")) 
278   {
279     _ringexit = 1;
280     if (CkMyPe()==0)
281       CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
282     if (_ringtoken > CkNumPes())  _ringtoken = CkNumPes();
283   }
284         /*
285                 FAULT_EVAC
286
287                 if the argument +raiseevac is present then cause faults
288         */
289         if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
290                 _raiseEvac = 1;
291         }
292 #ifdef _FAULT_MLOG_
293     if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
294         chkptPeriod = 100;
295     }
296     if(CmiGetArgFlagDesc(argv,"+Parallelrestart", "Parallel Restart with message logging protocol")){
297         parallelRestart = true;
298     }
299     if(!CmiGetArgIntDesc(argv,"+mlog_local_buffer",&_maxBufferedMessages,"# of local messages buffered in the message logging protoocl")){
300         _maxBufferedMessages = 2;
301     }
302     if(!CmiGetArgIntDesc(argv,"+mlog_remote_buffer",&_maxBufferedTicketRequests,"# of remote ticket requests buffered in the message logging protoocl")){
303         _maxBufferedTicketRequests = 2;
304     }
305     if(!CmiGetArgIntDesc(argv,"+mlog_buffer_time",&BUFFER_TIME,"# Time spent waiting for messages to be buffered in the message logging protoocl")){
306         BUFFER_TIME = 2;
307     }
308
309 #endif  
310         /* Anytime migration flag */
311         isAnytimeMigration = CmiTrue;
312         if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
313           isAnytimeMigration = CmiFalse;
314         }
315 }
316
317 static void _bufferHandler(void *msg)
318 {
319   DEBUGF(("[%d] _bufferHandler called.\n", CkMyPe()));
320   CkpvAccess(_buffQ)->enq(msg);
321 }
322
323 static void _discardHandler(envelope *env)
324 {
325   DEBUGF(("[%d] _discardHandler called.\n", CkMyPe()));
326   CmiFree(env);
327 }
328
329 #ifndef CMK_OPTIMIZE
330 static inline void _printStats(void)
331 {
332   DEBUGF(("[%d] _printStats\n", CkMyPe()));
333   int i;
334   if(_printSS || _printCS) {
335     Stats *total = new Stats();
336     _MEMCHECK(total);
337     for(i=0;i<CkNumPes();i++)
338       total->combine(_allStats[i]);
339     CkPrintf("Charm Kernel Summary Statistics:\n");
340     for(i=0;i<CkNumPes();i++) {
341       CkPrintf("Proc %d: [%d created, %d processed]\n", i,
342                _allStats[i]->getCharesCreated(),
343                _allStats[i]->getCharesProcessed());
344     }
345     CkPrintf("Total Chares: [%d created, %d processed]\n",
346              total->getCharesCreated(), total->getCharesProcessed());
347   }
348   if(_printCS) {
349     CkPrintf("Charm Kernel Detailed Statistics (R=requested P=processed):\n\n");
350
351     CkPrintf("         Create    Mesgs     Create    Mesgs     Create    Mesgs\n");
352     CkPrintf("         Chare     for       Group     for       Nodegroup for\n");
353     CkPrintf("PE   R/P Mesgs     Chares    Mesgs     Groups    Mesgs     Nodegroups\n");
354     CkPrintf("---- --- --------- --------- --------- --------- --------- ----------\n");
355
356     for(i=0;i<CkNumPes();i++) {
357       CkPrintf("%4d  R  %9d %9d %9d %9d %9d %9d\n      P  %9d %9d %9d %9d %9d %9d\n",i,
358                _allStats[i]->getCharesCreated(),
359                _allStats[i]->getForCharesCreated(),
360                _allStats[i]->getGroupsCreated(),
361                _allStats[i]->getGroupMsgsCreated(),
362                _allStats[i]->getNodeGroupsCreated(),
363                _allStats[i]->getNodeGroupMsgsCreated(),
364                _allStats[i]->getCharesProcessed(),
365                _allStats[i]->getForCharesProcessed(),
366                _allStats[i]->getGroupsProcessed(),
367                _allStats[i]->getGroupMsgsProcessed(),
368                _allStats[i]->getNodeGroupsProcessed(),
369                _allStats[i]->getNodeGroupMsgsProcessed());
370     }
371   }
372 }
373 #else
374 static inline void _printStats(void) {}
375 #endif
376
377 static inline void _sendStats(void)
378 {
379   DEBUGF(("[%d] _sendStats\n", CkMyPe()));
380 #ifndef CMK_OPTIMIZE
381   envelope *env = UsrToEnv(CkpvAccess(_myStats));
382 #else
383   envelope *env = _allocEnv(StatMsg);
384 #endif
385   env->setSrcPe(CkMyPe());
386   CmiSetHandler(env, _exitHandlerIdx);
387   CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
388 }
389
390 #ifdef _FAULT_MLOG_
391 extern void _messageLoggingExit();
392 #endif
393
394 static void _exitHandler(envelope *env)
395 {
396   DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
397   switch(env->getMsgtype()) {
398     case ExitMsg:
399       CkAssert(CkMyPe()==0);
400       if(_exitStarted) {
401         CmiFree(env);
402         return;
403       }
404       _exitStarted = 1;
405       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
406       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
407       env->setMsgtype(ReqStatMsg);
408       env->setSrcPe(CkMyPe());
409       // if exit in ring, instead of broadcasting, send in ring
410       if (_ringexit){
411         DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
412         const int stride = CkNumPes()/_ringtoken;
413         int pe = 0;
414         while (pe<CkNumPes()) {
415           CmiSyncSend(pe, env->getTotalsize(), (char *)env);
416           pe += stride;
417         }
418         CmiFree(env);
419       }else{
420         CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
421       } 
422       break;
423     case ReqStatMsg:
424 #ifdef _FAULT_MLOG_
425         _messageLoggingExit();
426 #endif
427       DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
428       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
429       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
430         /*FAULT_EVAC*/
431       if(CmiNodeAlive(CkMyPe())){
432          _sendStats();
433       } 
434       _mainDone = 1; // This is needed because the destructors for
435                      // readonly variables will be called when the program
436                      // exits. If the destructor is called while _mainDone
437                      // is 0, it will assume that the readonly variable was
438                      // declared locally. On all processors other than 0, 
439                      // _mainDone is never set to 1 before the program exits.
440 #ifndef CMK_OPTIMIZE
441       if (_ringexit) traceClose();
442 #endif
443       if (_ringexit) {
444         int stride = CkNumPes()/_ringtoken;
445         int pe = CkMyPe()+1;
446         if (pe < CkNumPes() && pe % stride != 0)
447           CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
448         else
449           CmiFree(env);
450       }
451       else
452         CmiFree(env);
453       if(CkMyPe()){
454         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
455         ConverseExit();
456       } 
457       break;
458     case StatMsg:
459       CkAssert(CkMyPe()==0);
460 #ifndef CMK_OPTIMIZE
461       _allStats[env->getSrcPe()] = (Stats*) EnvToUsr(env);
462 #endif
463       _numStatsRecd++;
464       DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), _numStatsRecd));
465                         /*FAULT_EVAC*/
466       if(_numStatsRecd==CkNumValidPes()) {
467         _printStats();
468         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
469         ConverseExit();
470       }
471       break;
472     default:
473       CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
474   }
475 }
476
477 /**
478  * Create all groups in this processor (not called on processor zero).
479  * Notice that only groups created in mainchares are processed here;
480  * groups created later are processed as regular messages.
481  */
482 static inline void _processBufferedBocInits(void)
483 {
484   CkCoreState *ck = CkpvAccess(_coreState);
485   CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler, ck);
486   register int i = 0;
487   PtrVec &inits=*CkpvAccess(_bocInitVec);
488   register int len = inits.size();
489   for(i=1; i<len; i++) {
490     envelope *env = inits[i];
491     if(env==0) CkAbort("_processBufferedBocInits: empty message");
492     if(env->isPacked())
493       CkUnpackMessage(&env);
494     _processBocInitMsg(ck,env);
495   }
496   delete &inits;
497 }
498
499 /**
500  * Create all nodegroups in this node (called only by rank zero, and never on node zero).
501  * Notice that only nodegroups created in mainchares are processed here;
502  * nodegroups created later are processed as regular messages.
503  */
504 static inline void _processBufferedNodeBocInits(void)
505 {
506   CkCoreState *ck = CkpvAccess(_coreState);
507   register int i = 0;
508   PtrVec &inits=*CksvAccess(_nodeBocInitVec);
509   register int len = inits.size();
510   for(i=1; i<len; i++) {
511     envelope *env = inits[i];
512     if(env==0) CkAbort("_processBufferedNodeBocInits: empty message");
513     if(env->isPacked())
514       CkUnpackMessage(&env);
515     _processNodeBocInitMsg(ck,env);
516   }
517   delete &inits;
518 }
519
520 static inline void _processBufferedMsgs(void)
521 {
522   CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler,
523         CkpvAccess(_coreState));
524   envelope *env;
525   while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
526     if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
527       if(env->isForAnyPE())
528         CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
529       else
530         _processHandler((void *)env, CkpvAccess(_coreState));
531     } else {
532       _processHandler((void *)env, CkpvAccess(_coreState));
533     }
534   }
535 }
536
537 static int _charmLoadEstimator(void)
538 {
539   return CkpvAccess(_buffQ)->length();
540 }
541
542 /**
543  * This function is used to send other processors on the same node a signal so
544  * they can check if their _initDone can be called: the reason for this is that
545  * the check at the end of _initHandler can fail due to a missing message containing
546  * a Nodegroup creation. When that message arrives only one processor will receive
547  * it, and thus if no notification is sent to the other processors in the node, they
548  * will never proceed.
549  */
550 static void _sendTriggers(void)
551 {
552   int i, num, first;
553   CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
554   if (_triggersSent == 0)
555   {
556     _triggersSent++;
557     num = CmiMyNodeSize();
558     register envelope *env = _allocEnv(RODataMsg); // Notice that the type here is irrelevant
559     env->setSrcPe(CkMyPe());
560     CmiSetHandler(env, _triggerHandlerIdx);
561     first = CmiNodeFirst(CmiMyNode());
562     for (i=0; i < num; i++)
563       if(first+i != CkMyPe())
564         CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
565     CmiFree(env);
566   }
567   CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
568 }
569
570 /**
571  * This function (not a handler) is called once and only once per processor.
572  * It signals the processor that the initialization is done and regular messages
573  * can be processed.
574  *
575  * On processor zero it is called by _initCharm, on all other processors either
576  * by _initHandler or _triggerHandler (cannot be both).
577  * When fault-tolerance is active, it is called by the fault-tolerance scheme itself.
578  */
579 void _initDone(void)
580 {
581   DEBUGF(("[%d] _initDone.\n", CkMyPe()));
582   if (!_triggersSent) _sendTriggers();
583   CkNumberHandler(_triggerHandlerIdx, (CmiHandler)_discardHandler);
584   CmiNodeBarrier();
585   if(CkMyRank() == 0) {
586     _processBufferedNodeBocInits();
587   }
588   CmiNodeBarrier(); // wait for all nodegroups to be created
589   _processBufferedBocInits();
590   DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
591   CmiNodeBarrier();
592   DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
593   _processBufferedMsgs();
594   CkpvAccess(_charmEpoch)=1;
595 }
596
597 /**
598  * Converse handler receiving a signal from another processors in the same node.
599  * (On _sendTrigger there is the explanation of why this is necessary)
600  * Simply check if with the NodeGroup processed by another processor we reached
601  * the expected count. Notice that it can only be called before _initDone: after
602  * _initDone, a message destined for this handler will go instead to the _discardHandler.
603  */
604 static void _triggerHandler(envelope *env)
605 {
606   if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
607   {
608     DEBUGF(("Calling Init Done from _triggerHandler\n"));
609     _initDone();
610   }
611   CmiFree(env);
612 }
613
614 static inline void _processROMsgMsg(envelope *env)
615 {
616   *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
617 }
618
619 static inline void _processRODataMsg(envelope *env)
620 {
621   //Unpack each readonly:
622   PUP::fromMem pu((char *)EnvToUsr(env));
623   for(size_t i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pu);
624   CmiFree(env);
625 }
626
627 /**
628  * This is similar to the _initHandler, only that the Groups and Nodegroups are
629  * initialized from disk, so only one single message is expected.
630  *
631  * It is unclear how Readonly Messages are treated during restart... (if at all considered)
632  */
633 static void _roRestartHandler(void *msg)
634 {
635   CkAssert(CkMyPe()!=0);
636   register envelope *env = (envelope *) msg;
637   CkpvAccess(_numInitsRecd)++;
638   _numExpectInitMsgs = env->getCount();
639   _processRODataMsg(env);
640 }
641
642 /**
643  * This handler is used only during initialization. It receives messages from
644  * processor zero regarding Readonly Data (in one single message), Readonly Messages,
645  * Groups, and Nodegroups.
646  * The Readonly Data message also contains the total number of messages expected
647  * during the initialization phase.
648  * For Groups and Nodegroups, only messages with epoch=0 (meaning created from within
649  * a mainchare) are buffered for special creation, the other messages are buffered
650  * together with all the other regular messages by _bufferHandler (and will be flushed
651  * after all the initialization messages have been processed).
652  */
653 static void _initHandler(void *msg, CkCoreState *ck)
654 {
655   CkAssert(CkMyPe()!=0);
656   register envelope *env = (envelope *) msg;
657   
658   if (ck->watcher!=NULL) {
659     if (!ck->watcher->processMessage(env,ck)) return;
660   }
661   
662   switch (env->getMsgtype()) {
663     case BocInitMsg:
664       if (env->getGroupEpoch()==0) {
665         CkpvAccess(_numInitsRecd)++;
666         // _processBocInitMsg already handles QD
667         //CpvAccess(_qd)->process();
668         CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
669       } else _bufferHandler(msg);
670       break;
671     case NodeBocInitMsg:
672       if (env->getGroupEpoch()==0) {
673         CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
674         CksvAccess(_numInitNodeMsgs)++;
675         CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
676         CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
677         CpvAccess(_qd)->process();
678       } else _bufferHandler(msg);
679       break;
680     case ROMsgMsg:
681       CkpvAccess(_numInitsRecd)++;
682       CpvAccess(_qd)->process();
683       if(env->isPacked()) CkUnpackMessage(&env);
684       _processROMsgMsg(env);
685       break;
686     case RODataMsg:
687       CkpvAccess(_numInitsRecd)++;
688       CpvAccess(_qd)->process();
689       _numExpectInitMsgs = env->getCount();
690       _processRODataMsg(env);
691       break;
692     default:
693       CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
694   }
695         DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
696   if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
697     _initDone();
698   }
699 }
700
701 // CkExit: start the termination process, but
702 //   then drop into the scheduler so the user's
703 //   method never returns (which would be confusing).
704 extern "C"
705 void _CkExit(void) 
706 {
707   // Shuts down Converse handlers for the upper layers on this processor
708   //
709   CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
710   CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
711   DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
712
713   if(CkMyPe()==0) {
714     if(_exitStarted)
715       CsdScheduler(-1);
716     envelope *env = _allocEnv(ReqStatMsg);
717     env->setSrcPe(CkMyPe());
718     CmiSetHandler(env, _exitHandlerIdx);
719                 /*FAULT_EVAC*/
720     CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
721   } else {
722     envelope *env = _allocEnv(ExitMsg);
723     env->setSrcPe(CkMyPe());
724     CmiSetHandler(env, _exitHandlerIdx);
725     CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
726   }
727 #if ! CMK_BLUEGENE_THREAD
728   _TRACE_END_EXECUTE();
729   //Wait for stats, which will call ConverseExit when finished:
730   CsdScheduler(-1);
731 #endif
732 }
733
734 CkQ<CkExitFn> _CkExitFnVec;
735
736 // wrapper of CkExit
737 // traverse _CkExitFnVec to call registered user exit functions
738 // CkExitFn will call CkExit() when finished to make sure other
739 // registered functions get called.
740 extern "C"
741 void CkExit(void)
742 {
743         /*FAULT_EVAC*/
744         DEBUGF(("[%d] CkExit called \n",CkMyPe()));
745   if (!_CkExitFnVec.isEmpty()) {
746     CkExitFn fn = _CkExitFnVec.deq();
747     fn();
748   }
749   else
750     _CkExit();
751 }
752
753 /* This is a routine called in case the application is closing due to a signal.
754    Tear down structures that must be cleaned up even when unclean exit happens.
755    It is called by the machine layer whenever some problem occurs (it is thus up
756    to the machine layer to call this function). */
757 extern "C"
758 void EmergencyExit(void) {
759 #ifndef __BLUEGENE__
760   /* Delete _coreState to force any CkMessageWatcher to close down. */
761   delete CkpvAccess(_coreState);
762 #endif
763 }
764
765 static void _nullFn(void *, void *)
766 {
767   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
768 }
769
770 extern void _registerLBDatabase(void);
771 extern void _registerPathHistory(void);
772 extern void _registerExternalModules(char **argv);
773 extern void _ckModuleInit(void);
774 extern void _loadbalancerInit();
775 #if CMK_MEM_CHECKPOINT
776 extern void init_memcheckpt(char **argv);
777 #endif
778 extern "C" void initCharmProjections();
779 extern "C" void CmiInitCPUTopology(char **argv);
780 extern "C" void CmiInitCPUAffinity(char **argv);
781
782 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
783 {
784   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
785   else _initCallTable.initProcCalls.enq(fn);
786 }
787
788 void InitCallTable::enumerateInitCalls()
789 {
790   int i;
791 #ifdef __BLUEGENE__
792   if(BgNodeRank()==0)        // called only once on an emulating node
793 #else
794   if(CkMyRank()==0) 
795 #endif
796   {
797     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
798   }
799   // initproc may depend on initnode calls.
800   CmiNodeAllBarrier();
801   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
802 }
803
804 CpvCExtern(int, cpdSuspendStartup);
805 extern "C" void CpdFreeze(void);
806
807 extern int _dummy_dq;
808
809 extern "C" void initQd(char **argv)
810 {
811         CpvInitialize(QdState*, _qd);
812         CpvAccess(_qd) = new QdState();
813         if (CmiMyRank() == 0) {
814 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
815         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
816 #endif
817         }
818         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
819         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
820         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
821           if (CmiMyPe()==0)
822             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
823         }
824 }
825
826 /**
827   This is the main charm setup routine.  It's called
828   on all processors after Converse initialization.
829   This routine gets passed to Converse from "main.C".
830   
831   The main purpose of this routine is to set up the objects
832   and Ckpv's used during a regular Charm run.  See the comment
833   at the top of the file for overall flow.
834 */
835 void _initCharm(int unused_argc, char **argv)
836
837         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
838
839         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
840
841         CkpvInitialize(PtrQ*,_buffQ);
842         CkpvInitialize(PtrVec*,_bocInitVec);
843         CkpvInitialize(void*, _currentChare);
844         CkpvInitialize(int,   _currentChareType);
845         CkpvInitialize(CkGroupID, _currentGroup);
846         CkpvInitialize(void *, _currentNodeGroupObj);
847         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
848         CkpvInitialize(GroupTable*, _groupTable);
849         CkpvInitialize(GroupIDTable*, _groupIDTable);
850         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
851         CkpvInitialize(UInt, _numGroups);
852         CkpvInitialize(int, _numInitsRecd);
853         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
854         CkpvInitialize(MsgPool*, _msgPool);
855         CkpvInitialize(CkCoreState *, _coreState);
856         /*
857                 Added for evacuation-sayantan
858         */
859 #ifndef __BLUEGENE__
860         CpvInitialize(char *,_validProcessors);
861         CpvInitialize(char ,startedEvac);
862 #endif
863         CpvInitialize(int,serializer);
864
865 #ifndef CMK_CHARE_USE_PTR
866           /* chare and vidblock table */
867         CpvInitialize(CkVec<void *>, chare_objs);
868         CpvInitialize(CkVec<int>, chare_types);
869         CpvInitialize(CkVec<VidBlock *>, vidblocks);
870 #endif
871
872         CksvInitialize(UInt, _numNodeGroups);
873         CksvInitialize(GroupTable*, _nodeGroupTable);
874         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
875         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
876         CksvInitialize(CmiNodeLock, _nodeLock);
877         CksvInitialize(PtrVec*,_nodeBocInitVec);
878         CksvInitialize(UInt,_numInitNodeMsgs);
879         CkpvInitialize(int,_charmEpoch);
880         CkpvAccess(_charmEpoch)=0;
881
882         CkpvInitialize(_CkOutStream*, _ckout);
883         CkpvInitialize(_CkErrStream*, _ckerr);
884         CkpvInitialize(Stats*, _myStats);
885
886         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
887         CkpvAccess(_groupTable) = new GroupTable;
888         CkpvAccess(_groupTable)->init();
889         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
890         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
891         CkpvAccess(_buffQ) = new PtrQ();
892         CkpvAccess(_bocInitVec) = new PtrVec();
893
894         CkpvAccess(_currentNodeGroupObj) = NULL;
895
896         if(CkMyRank()==0)
897         {
898                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
899                 CksvAccess(_numInitNodeMsgs) = 0;
900                 CksvAccess(_nodeLock) = CmiCreateLock();
901                 CksvAccess(_nodeGroupTable) = new GroupTable();
902                 CksvAccess(_nodeGroupTable)->init();
903                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
904                 CksvAccess(_nodeBocInitVec) = new PtrVec();
905         }
906
907         CkCallbackInit();
908         
909         CmiNodeAllBarrier();
910
911 #if ! CMK_BLUEGENE_CHARM
912         initQd(argv);         // bigsim calls it in ConverseCommonInit
913 #endif
914
915         CkpvAccess(_coreState)=new CkCoreState();
916
917         CkpvAccess(_numInitsRecd) = 0;
918
919         CkpvAccess(_ckout) = new _CkOutStream();
920         CkpvAccess(_ckerr) = new _CkErrStream();
921
922         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
923         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
924         CkNumberHandlerEx(_initHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
925         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
926         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
927         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
928         CkNumberHandlerEx(_bocHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
929         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
930         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
931         _ckModuleInit();
932
933         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
934
935         _futuresModuleInit(); // part of futures implementation is a converse module
936         _loadbalancerInit();
937         
938 #if CMK_MEM_CHECKPOINT
939         init_memcheckpt(argv);
940 #endif
941
942         initCharmProjections();
943 #if CMK_TRACE_IN_CHARM
944         // initialize trace module in ck
945         traceCharmInit(argv);
946 #endif
947         
948     CkpvInitialize(int, envelopeEventID);
949     CkpvAccess(envelopeEventID) = 0;
950         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
951         
952         /**
953           The rank-0 processor of each node calls the 
954           translator-generated "_register" routines. 
955           
956           _register routines call the charm.h "CkRegister*" routines,
957           which record function pointers and class information for
958           all Charm entities, like Chares, Arrays, and readonlies.
959           
960           There's one _register routine generated for each
961           .ci file.  _register routines *must* be called in the 
962           same order on every node, and *must not* be called by 
963           multiple threads simultaniously.
964         */
965 #ifdef __BLUEGENE__
966         if(BgNodeRank()==0) 
967 #else
968         if(CkMyRank()==0)
969 #endif
970         {
971                 CmiArgGroup("Charm++",NULL);
972                 _parseCommandLineOpts(argv);
973                 _registerInit();
974                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
975                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
976                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
977                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
978                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
979                 CkRegisterChareInCharm(CkIndex_Group::__idx);
980                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
981                 
982                 /**
983                   These _register calls are for the built-in
984                   Charm .ci files, like arrays and load balancing.
985                   If you add a .ci file to charm, you'll have to 
986                   add a call to the _register routine here, or make
987                   your library into a "-module".
988                 */
989                 _registerCkFutures();
990                 _registerCkArray();
991                 _registerLBDatabase();
992                 _registerCkCallback();
993                 _registertempo();
994                 _registerwaitqd();
995                 _registercharisma();
996                 _registerCkCheckpoint();
997 #if CMK_MEM_CHECKPOINT
998                 _registerCkMemCheckpoint();
999 #endif
1000                 
1001                 _registerPathHistory();
1002
1003                 /**
1004                   _registerExternalModules is actually generated by 
1005                   charmc at link time (as "moduleinit<pid>.C").  
1006                   
1007                   This generated routine calls the _register functions
1008                   for the .ci files of libraries linked using "-module".
1009                   This funny initialization is most useful for AMPI/FEM
1010                   programs, which don't have a .ci file and hence have
1011                   no other way to control the _register process.
1012                 */
1013                 _registerExternalModules(argv);
1014                 
1015                 /**
1016                   CkRegisterMainModule is generated by the (unique)
1017                   "mainmodule" .ci file.  It will include calls to 
1018                   register all the .ci files.
1019                 */
1020                 CkRegisterMainModule();
1021                 _registerDone();
1022         }
1023         CmiNodeAllBarrier();
1024
1025     // Execute the initcalls registered in modules
1026         _initCallTable.enumerateInitCalls();
1027
1028 #ifndef CMK_OPTIMIZE
1029 #ifdef __BLUEGENE__
1030         if(BgNodeRank()==0)
1031 #else
1032         if(CkMyRank()==0)
1033 #endif
1034           CpdFinishInitialization();
1035 #endif
1036
1037         //CmiNodeAllBarrier();
1038
1039         CkpvAccess(_myStats) = new Stats();
1040         CkpvAccess(_msgPool) = new MsgPool();
1041
1042         CmiNodeAllBarrier();
1043 #if CMK_SMP_TRACE_COMMTHREAD
1044         _TRACE_BEGIN_COMPUTATION();     
1045 #else
1046         if (!inCommThread) {
1047           _TRACE_BEGIN_COMPUTATION();
1048         }
1049 #endif
1050
1051 #ifdef ADAPT_SCHED_MEM
1052     if(CkMyRank()==0){
1053         memCriticalEntries = new int[numMemCriticalEntries];
1054         int memcnt=0;
1055         for(int i=0; i<_entryTable.size(); i++){
1056             if(_entryTable[i]->isMemCritical){
1057                 memCriticalEntries[memcnt++] = i;
1058             }
1059         }
1060     }
1061 #endif
1062
1063 #ifdef _FAULT_MLOG_
1064     _messageLoggingInit();
1065 #endif
1066
1067 #ifndef __BLUEGENE__
1068         /*
1069                 FAULT_EVAC
1070         */
1071         CpvAccess(_validProcessors) = new char[CkNumPes()];
1072         for(int vProc=0;vProc<CkNumPes();vProc++){
1073                 CpvAccess(_validProcessors)[vProc]=1;
1074         }
1075         CpvAccess(startedEvac) = 0;
1076         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
1077         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
1078 #endif
1079         CpvAccess(serializer) = 0;
1080
1081         evacuate = 0;
1082         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1083 #ifdef _FAULT_MLOG_ 
1084     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1085 #endif
1086
1087         if(_raiseEvac){
1088                 processRaiseEvacFile(_raiseEvacFile);
1089                 /*
1090                 if(CkMyPe() == 2){
1091                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1092                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1093                 }
1094                 if(CkMyPe() == 3){
1095                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1096                 }*/
1097         }       
1098         
1099         if (faultFunc == NULL && !replaySystem) {         // this is not restart
1100             // these two are blocking calls for non-bigsim
1101 #if ! CMK_BLUEGENE_CHARM
1102           CmiInitCPUAffinity(argv);
1103 #endif
1104           CmiInitCPUTopology(argv);
1105         }
1106
1107         if (faultFunc) {
1108                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1109                 if (!inCommThread) {
1110                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1111                   msg->argc = CmiGetArgc(argv);
1112                   msg->argv = argv;
1113                   faultFunc(_restartDir, msg);
1114                   CkFreeMsg(msg);
1115                 }
1116         }else if(CkMyPe()==0){
1117                 _allStats = new Stats*[CkNumPes()];
1118                 register size_t i, nMains=_mainTable.size();
1119                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1120                 {
1121                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1122                         register void *obj = malloc(size);
1123                         _MEMCHECK(obj);
1124                         _mainTable[i]->setObj(obj);
1125                         CkpvAccess(_currentChare) = obj;
1126                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1127                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1128                         msg->argc = CmiGetArgc(argv);
1129                         msg->argv = argv;
1130                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1131 #ifdef _FAULT_MLOG_
1132             CpvAccess(_currentObj) = (Chare *)obj;
1133 #endif
1134                 }
1135                 _mainDone = 1;
1136
1137                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1138                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1139
1140
1141
1142
1143                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1144                 {
1145                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1146                         if(roMsg==0)
1147                                 continue;
1148                         //Pack the message and send it to all other processors
1149                         register envelope *env = UsrToEnv(roMsg);
1150                         env->setSrcPe(CkMyPe());
1151                         env->setMsgtype(ROMsgMsg);
1152                         env->setRoIdx(i);
1153                         CmiSetHandler(env, _initHandlerIdx);
1154                         CkPackMessage(&env);
1155                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1156                         CpvAccess(_qd)->create(CkNumPes()-1);
1157
1158                         //For processor 0, unpack and re-set the global
1159                         CkUnpackMessage(&env);
1160                         _processROMsgMsg(env);
1161                         _numInitMsgs++;
1162                 }
1163
1164                 //Determine the size of the RODataMessage
1165                 PUP::sizer ps;
1166                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1167
1168                 //Allocate and fill out the RODataMessage
1169                 envelope *env = _allocEnv(RODataMsg, ps.size());
1170                 PUP::toMem pp((char *)EnvToUsr(env));
1171                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1172
1173                 env->setCount(++_numInitMsgs);
1174                 env->setSrcPe(CkMyPe());
1175                 CmiSetHandler(env, _initHandlerIdx);
1176                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1177                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1178                 CpvAccess(_qd)->create(CkNumPes()-1);
1179                 _initDone();
1180         }
1181
1182         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1183         // when I am a communication thread, I don't participate initDone.
1184         if (inCommThread) {
1185                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1186                                         CkpvAccess(_coreState));
1187                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1188 ,
1189                                         CkpvAccess(_coreState));
1190         }
1191
1192 #if CMK_CCS_AVAILABLE
1193        if (CpvAccess(cpdSuspendStartup))
1194        { 
1195           //CmiPrintf("In Parallel Debugging mode .....\n");
1196           CpdFreeze();
1197        }
1198 #endif
1199
1200
1201 #if __FAULT__
1202         if(killFlag){                                                  
1203                 readKillFile();                                        
1204         }
1205 #endif
1206
1207 }
1208
1209 // this is needed because on o2k, f90 programs have to have main in
1210 // fortran90.
1211 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1212 {
1213   int i;
1214   char **argv = new char*[*argc+2];
1215
1216   for(i=0;i <= *argc;i++) {
1217     if (length[i] < 100) {
1218       _argv[i][length[i]]='\0';
1219       argv[i] = &(_argv[i][0]);
1220     } else {
1221       argv[i][0] = '\0';
1222     }
1223   }
1224   argv[*argc+1]=0;
1225
1226   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1227 }
1228
1229 // user callable function to register an exit function, this function
1230 // will perform task of collecting of info from all pes to pe0, and call
1231 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1232 // see trace-summary for an example.
1233 void registerExitFn(CkExitFn fn)
1234 {
1235   _CkExitFnVec.enq(fn);
1236 }
1237
1238 /*@}*/