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