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