591413043942c338881809a15c9c3a1d6f741f16
[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 CpvDeclare(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   delete CkpvAccess(_coreState);
788 #endif
789 }
790
791 static void _nullFn(void *, void *)
792 {
793   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
794 }
795
796 extern void _registerLBDatabase(void);
797 extern void _registerPathHistory(void);
798 extern void _registerExternalModules(char **argv);
799 extern void _ckModuleInit(void);
800 extern void _loadbalancerInit();
801 extern void _initChareTables();
802 #if CMK_MEM_CHECKPOINT
803 extern void init_memcheckpt(char **argv);
804 #endif
805 extern "C" void initCharmProjections();
806 extern "C" void CmiInitCPUTopology(char **argv);
807 extern "C" void CmiInitCPUAffinity(char **argv);
808
809 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
810 {
811   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
812   else _initCallTable.initProcCalls.enq(fn);
813 }
814
815 void InitCallTable::enumerateInitCalls()
816 {
817   int i;
818 #ifdef __BLUEGENE__
819   if(BgNodeRank()==0)        // called only once on an emulating node
820 #else
821   if(CkMyRank()==0) 
822 #endif
823   {
824     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
825   }
826   // initproc may depend on initnode calls.
827   CmiNodeAllBarrier();
828   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
829 }
830
831 CpvCExtern(int, cpdSuspendStartup);
832 extern "C" void CpdFreeze(void);
833
834 extern int _dummy_dq;
835
836 extern "C" void initQd(char **argv)
837 {
838         CpvInitialize(QdState*, _qd);
839         CpvAccess(_qd) = new QdState();
840         if (CmiMyRank() == 0) {
841 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
842         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
843 #endif
844         }
845         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
846         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
847         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
848           if (CmiMyPe()==0)
849             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
850         }
851 }
852
853 /**
854   This is the main charm setup routine.  It's called
855   on all processors after Converse initialization.
856   This routine gets passed to Converse from "main.C".
857   
858   The main purpose of this routine is to set up the objects
859   and Ckpv's used during a regular Charm run.  See the comment
860   at the top of the file for overall flow.
861 */
862 void _initCharm(int unused_argc, char **argv)
863
864         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
865
866         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
867
868         CkpvInitialize(PtrQ*,_buffQ);
869         CkpvInitialize(PtrVec*,_bocInitVec);
870         CkpvInitialize(void*, _currentChare);
871         CkpvInitialize(int,   _currentChareType);
872         CkpvInitialize(CkGroupID, _currentGroup);
873         CkpvInitialize(void *, _currentNodeGroupObj);
874         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
875         CkpvInitialize(GroupTable*, _groupTable);
876         CkpvInitialize(GroupIDTable*, _groupIDTable);
877         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
878         CkpvInitialize(UInt, _numGroups);
879         CkpvInitialize(int, _numInitsRecd);
880         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
881         CkpvInitialize(MsgPool*, _msgPool);
882         CkpvInitialize(CkCoreState *, _coreState);
883         /*
884                 Added for evacuation-sayantan
885         */
886 #ifndef __BLUEGENE__
887         CpvInitialize(char *,_validProcessors);
888         CpvInitialize(char ,startedEvac);
889 #endif
890         CpvInitialize(int,serializer);
891
892         _initChareTables();            // for checkpointable plain chares
893
894         CksvInitialize(UInt, _numNodeGroups);
895         CksvInitialize(GroupTable*, _nodeGroupTable);
896         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
897         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
898         CksvInitialize(CmiNodeLock, _nodeLock);
899         CksvInitialize(PtrVec*,_nodeBocInitVec);
900         CksvInitialize(UInt,_numInitNodeMsgs);
901         CkpvInitialize(int,_charmEpoch);
902         CkpvAccess(_charmEpoch)=0;
903         CksvInitialize(int, _triggersSent);
904         CksvAccess(_triggersSent) = 0;
905
906         CkpvInitialize(_CkOutStream*, _ckout);
907         CkpvInitialize(_CkErrStream*, _ckerr);
908         CkpvInitialize(Stats*, _myStats);
909
910         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
911         CkpvAccess(_groupTable) = new GroupTable;
912         CkpvAccess(_groupTable)->init();
913         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
914         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
915         CkpvAccess(_buffQ) = new PtrQ();
916         CkpvAccess(_bocInitVec) = new PtrVec();
917
918         CkpvAccess(_currentNodeGroupObj) = NULL;
919
920         if(CkMyRank()==0)
921         {
922                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
923                 CksvAccess(_numInitNodeMsgs) = 0;
924                 CksvAccess(_nodeLock) = CmiCreateLock();
925                 CksvAccess(_nodeGroupTable) = new GroupTable();
926                 CksvAccess(_nodeGroupTable)->init();
927                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
928                 CksvAccess(_nodeBocInitVec) = new PtrVec();
929         }
930
931         CkCallbackInit();
932         
933         CmiNodeAllBarrier();
934
935 #if ! CMK_BLUEGENE_CHARM
936         initQd(argv);         // bigsim calls it in ConverseCommonInit
937 #endif
938
939         CkpvAccess(_coreState)=new CkCoreState();
940
941         CkpvAccess(_numInitsRecd) = 0;
942
943         CkpvAccess(_ckout) = new _CkOutStream();
944         CkpvAccess(_ckerr) = new _CkErrStream();
945
946         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
947         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
948         CkNumberHandlerEx(_initHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
949         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
950         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
951         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
952         CkNumberHandlerEx(_bocHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
953         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
954         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
955         _ckModuleInit();
956
957         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
958
959         _futuresModuleInit(); // part of futures implementation is a converse module
960         _loadbalancerInit();
961         
962 #if CMK_MEM_CHECKPOINT
963         init_memcheckpt(argv);
964 #endif
965
966         initCharmProjections();
967 #if CMK_TRACE_IN_CHARM
968         // initialize trace module in ck
969         traceCharmInit(argv);
970 #endif
971         
972     CkpvInitialize(int, envelopeEventID);
973     CkpvAccess(envelopeEventID) = 0;
974         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
975         
976         /**
977           The rank-0 processor of each node calls the 
978           translator-generated "_register" routines. 
979           
980           _register routines call the charm.h "CkRegister*" routines,
981           which record function pointers and class information for
982           all Charm entities, like Chares, Arrays, and readonlies.
983           
984           There's one _register routine generated for each
985           .ci file.  _register routines *must* be called in the 
986           same order on every node, and *must not* be called by 
987           multiple threads simultaniously.
988         */
989 #ifdef __BLUEGENE__
990         if(BgNodeRank()==0) 
991 #else
992         if(CkMyRank()==0)
993 #endif
994         {
995                 CmiArgGroup("Charm++",NULL);
996                 _parseCommandLineOpts(argv);
997                 _registerInit();
998                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
999                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1000                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1001                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1002                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1003                 CkRegisterChareInCharm(CkIndex_Group::__idx);
1004                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1005                 
1006                 /**
1007                   These _register calls are for the built-in
1008                   Charm .ci files, like arrays and load balancing.
1009                   If you add a .ci file to charm, you'll have to 
1010                   add a call to the _register routine here, or make
1011                   your library into a "-module".
1012                 */
1013                 _registerCkFutures();
1014                 _registerCkArray();
1015                 _registerLBDatabase();
1016                 _registerCkCallback();
1017                 _registertempo();
1018                 _registerwaitqd();
1019                 _registercharisma();
1020                 _registerCkCheckpoint();
1021 #if CMK_MEM_CHECKPOINT
1022                 _registerCkMemCheckpoint();
1023 #endif
1024                 
1025                 _registerPathHistory();
1026
1027                 /**
1028                   _registerExternalModules is actually generated by 
1029                   charmc at link time (as "moduleinit<pid>.C").  
1030                   
1031                   This generated routine calls the _register functions
1032                   for the .ci files of libraries linked using "-module".
1033                   This funny initialization is most useful for AMPI/FEM
1034                   programs, which don't have a .ci file and hence have
1035                   no other way to control the _register process.
1036                 */
1037                 _registerExternalModules(argv);
1038                 
1039                 /**
1040                   CkRegisterMainModule is generated by the (unique)
1041                   "mainmodule" .ci file.  It will include calls to 
1042                   register all the .ci files.
1043                 */
1044                 CkRegisterMainModule();
1045                 _registerDone();
1046         }
1047         CmiNodeAllBarrier();
1048
1049     // Execute the initcalls registered in modules
1050         _initCallTable.enumerateInitCalls();
1051
1052 #ifndef CMK_OPTIMIZE
1053 #ifdef __BLUEGENE__
1054         if(BgNodeRank()==0)
1055 #else
1056         if(CkMyRank()==0)
1057 #endif
1058           CpdFinishInitialization();
1059 #endif
1060
1061         //CmiNodeAllBarrier();
1062
1063         CkpvAccess(_myStats) = new Stats();
1064         CkpvAccess(_msgPool) = new MsgPool();
1065
1066         CmiNodeAllBarrier();
1067 #if CMK_SMP_TRACE_COMMTHREAD
1068         _TRACE_BEGIN_COMPUTATION();     
1069 #else
1070         if (!inCommThread) {
1071           _TRACE_BEGIN_COMPUTATION();
1072         }
1073 #endif
1074
1075 #ifdef ADAPT_SCHED_MEM
1076     if(CkMyRank()==0){
1077         memCriticalEntries = new int[numMemCriticalEntries];
1078         int memcnt=0;
1079         for(int i=0; i<_entryTable.size(); i++){
1080             if(_entryTable[i]->isMemCritical){
1081                 memCriticalEntries[memcnt++] = i;
1082             }
1083         }
1084     }
1085 #endif
1086
1087 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1088     _messageLoggingInit();
1089 #endif
1090
1091 #ifndef __BLUEGENE__
1092         /*
1093                 FAULT_EVAC
1094         */
1095         CpvAccess(_validProcessors) = new char[CkNumPes()];
1096         for(int vProc=0;vProc<CkNumPes();vProc++){
1097                 CpvAccess(_validProcessors)[vProc]=1;
1098         }
1099         CpvAccess(startedEvac) = 0;
1100         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
1101         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
1102 #endif
1103         CpvAccess(serializer) = 0;
1104
1105         evacuate = 0;
1106         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1107 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
1108     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1109 #endif
1110
1111         if(_raiseEvac){
1112                 processRaiseEvacFile(_raiseEvacFile);
1113                 /*
1114                 if(CkMyPe() == 2){
1115                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1116                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1117                 }
1118                 if(CkMyPe() == 3){
1119                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1120                 }*/
1121         }       
1122
1123     if (!_replaySystem) {
1124         if (faultFunc == NULL) {         // this is not restart
1125             // these two are blocking calls for non-bigsim
1126 #if ! CMK_BLUEGENE_CHARM
1127           CmiInitCPUAffinity(argv);
1128 #endif
1129         }
1130         CmiInitCPUTopology(argv);
1131     }
1132
1133         if (faultFunc) {
1134                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1135                 if (!inCommThread) {
1136                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1137                   msg->argc = CmiGetArgc(argv);
1138                   msg->argv = argv;
1139                   faultFunc(_restartDir, msg);
1140                   CkFreeMsg(msg);
1141                 }
1142         }else if(CkMyPe()==0){
1143                 _allStats = new Stats*[CkNumPes()];
1144                 register size_t i, nMains=_mainTable.size();
1145                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1146                 {
1147                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1148                         register void *obj = malloc(size);
1149                         _MEMCHECK(obj);
1150                         _mainTable[i]->setObj(obj);
1151                         CkpvAccess(_currentChare) = obj;
1152                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1153                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1154                         msg->argc = CmiGetArgc(argv);
1155                         msg->argv = argv;
1156                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1157 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1158             CpvAccess(_currentObj) = (Chare *)obj;
1159 #endif
1160                 }
1161                 _mainDone = 1;
1162
1163                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1164                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1165
1166
1167
1168
1169                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1170                 {
1171                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1172                         if(roMsg==0)
1173                                 continue;
1174                         //Pack the message and send it to all other processors
1175                         register envelope *env = UsrToEnv(roMsg);
1176                         env->setSrcPe(CkMyPe());
1177                         env->setMsgtype(ROMsgMsg);
1178                         env->setRoIdx(i);
1179                         CmiSetHandler(env, _initHandlerIdx);
1180                         CkPackMessage(&env);
1181                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1182                         CpvAccess(_qd)->create(CkNumPes()-1);
1183
1184                         //For processor 0, unpack and re-set the global
1185                         CkUnpackMessage(&env);
1186                         _processROMsgMsg(env);
1187                         _numInitMsgs++;
1188                 }
1189
1190                 //Determine the size of the RODataMessage
1191                 PUP::sizer ps;
1192                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1193
1194                 //Allocate and fill out the RODataMessage
1195                 envelope *env = _allocEnv(RODataMsg, ps.size());
1196                 PUP::toMem pp((char *)EnvToUsr(env));
1197                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1198
1199                 env->setCount(++_numInitMsgs);
1200                 env->setSrcPe(CkMyPe());
1201                 CmiSetHandler(env, _initHandlerIdx);
1202                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1203                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1204                 CpvAccess(_qd)->create(CkNumPes()-1);
1205                 _initDone();
1206         }
1207
1208         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1209         // when I am a communication thread, I don't participate initDone.
1210         if (inCommThread) {
1211                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1212                                         CkpvAccess(_coreState));
1213                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1214 ,
1215                                         CkpvAccess(_coreState));
1216         }
1217
1218 #if CMK_CCS_AVAILABLE
1219        if (CpvAccess(cpdSuspendStartup))
1220        { 
1221           //CmiPrintf("In Parallel Debugging mode .....\n");
1222           CpdFreeze();
1223        }
1224 #endif
1225
1226
1227 #if __FAULT__
1228         if(killFlag){                                                  
1229                 readKillFile();                                        
1230         }
1231 #endif
1232
1233 }
1234
1235 // this is needed because on o2k, f90 programs have to have main in
1236 // fortran90.
1237 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1238 {
1239   int i;
1240   char **argv = new char*[*argc+2];
1241
1242   for(i=0;i <= *argc;i++) {
1243     if (length[i] < 100) {
1244       _argv[i][length[i]]='\0';
1245       argv[i] = &(_argv[i][0]);
1246     } else {
1247       argv[i][0] = '\0';
1248     }
1249   }
1250   argv[*argc+1]=0;
1251
1252   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1253 }
1254
1255 // user callable function to register an exit function, this function
1256 // will perform task of collecting of info from all pes to pe0, and call
1257 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1258 // see trace-summary for an example.
1259 void registerExitFn(CkExitFn fn)
1260 {
1261   _CkExitFnVec.enq(fn);
1262 }
1263
1264 /*@}*/