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