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