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