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