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