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