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