d9503f9260080376d6fe4edc9b925fbc526e2d73
[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 #ifndef CMK_OPTIMIZE
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",&cur_restart_phase,"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 #ifndef CMK_OPTIMIZE
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 #ifndef CMK_OPTIMIZE
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 #ifndef CMK_OPTIMIZE
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(PtrQ*,_buffQ);
933         CkpvInitialize(PtrVec*,_bocInitVec);
934         CkpvInitialize(void*, _currentChare);
935         CkpvInitialize(int,   _currentChareType);
936         CkpvInitialize(CkGroupID, _currentGroup);
937         CkpvInitialize(void *, _currentNodeGroupObj);
938         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
939         CkpvInitialize(GroupTable*, _groupTable);
940         CkpvInitialize(GroupIDTable*, _groupIDTable);
941         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
942         CkpvInitialize(UInt, _numGroups);
943         CkpvInitialize(int, _numInitsRecd);
944         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
945         CkpvInitialize(MsgPool*, _msgPool);
946         CkpvInitialize(CkCoreState *, _coreState);
947         /*
948                 Added for evacuation-sayantan
949         */
950 #ifndef __BLUEGENE__
951         CpvInitialize(char *,_validProcessors);
952         CpvInitialize(char ,startedEvac);
953 #endif
954         CpvInitialize(int,serializer);
955
956         _initChareTables();            // for checkpointable plain chares
957
958         CksvInitialize(UInt, _numNodeGroups);
959         CksvInitialize(GroupTable*, _nodeGroupTable);
960         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
961         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
962         CksvInitialize(CmiNodeLock, _nodeLock);
963         CksvInitialize(PtrVec*,_nodeBocInitVec);
964         CksvInitialize(UInt,_numInitNodeMsgs);
965         CkpvInitialize(int,_charmEpoch);
966         CkpvAccess(_charmEpoch)=0;
967         CksvInitialize(int, _triggersSent);
968         CksvAccess(_triggersSent) = 0;
969
970         CkpvInitialize(_CkOutStream*, _ckout);
971         CkpvInitialize(_CkErrStream*, _ckerr);
972         CkpvInitialize(Stats*, _myStats);
973
974         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
975         CkpvAccess(_groupTable) = new GroupTable;
976         CkpvAccess(_groupTable)->init();
977         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
978         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
979         CkpvAccess(_buffQ) = new PtrQ();
980         CkpvAccess(_bocInitVec) = new PtrVec();
981
982         CkpvAccess(_currentNodeGroupObj) = NULL;
983
984         if(CkMyRank()==0)
985         {
986                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
987                 CksvAccess(_numInitNodeMsgs) = 0;
988                 CksvAccess(_nodeLock) = CmiCreateLock();
989                 CksvAccess(_nodeGroupTable) = new GroupTable();
990                 CksvAccess(_nodeGroupTable)->init();
991                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
992                 CksvAccess(_nodeBocInitVec) = new PtrVec();
993         }
994
995         CkCallbackInit();
996         
997         CmiNodeAllBarrier();
998
999 #if ! CMK_BLUEGENE_CHARM
1000         initQd(argv);         // bigsim calls it in ConverseCommonInit
1001 #endif
1002
1003         CkpvAccess(_coreState)=new CkCoreState();
1004
1005         CkpvAccess(_numInitsRecd) = 0;
1006
1007         CkpvAccess(_ckout) = new _CkOutStream();
1008         CkpvAccess(_ckerr) = new _CkErrStream();
1009
1010         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
1011         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
1012         CkNumberHandlerEx(_initHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
1013         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
1014         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
1015         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
1016         CkNumberHandlerEx(_bocHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
1017
1018 #ifdef __BLUEGENE__
1019         if(BgNodeRank()==0) 
1020 #endif
1021         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1022
1023         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
1024         _ckModuleInit();
1025
1026         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1027
1028         _futuresModuleInit(); // part of futures implementation is a converse module
1029         _loadbalancerInit();
1030         
1031 #if CMK_MEM_CHECKPOINT
1032         init_memcheckpt(argv);
1033 #endif
1034
1035         initCharmProjections();
1036 #if CMK_TRACE_IN_CHARM
1037         // initialize trace module in ck
1038         traceCharmInit(argv);
1039 #endif
1040         
1041     CkpvInitialize(int, envelopeEventID);
1042     CkpvAccess(envelopeEventID) = 0;
1043         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1044         
1045         /**
1046           The rank-0 processor of each node calls the 
1047           translator-generated "_register" routines. 
1048           
1049           _register routines call the charm.h "CkRegister*" routines,
1050           which record function pointers and class information for
1051           all Charm entities, like Chares, Arrays, and readonlies.
1052           
1053           There's one _register routine generated for each
1054           .ci file.  _register routines *must* be called in the 
1055           same order on every node, and *must not* be called by 
1056           multiple threads simultaniously.
1057         */
1058 #ifdef __BLUEGENE__
1059         if(BgNodeRank()==0) 
1060 #else
1061         if(CkMyRank()==0)
1062 #endif
1063         {
1064                 CmiArgGroup("Charm++",NULL);
1065                 _parseCommandLineOpts(argv);
1066                 _registerInit();
1067                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1068                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1069                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1070                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1071                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1072                 CkRegisterChareInCharm(CkIndex_Group::__idx);
1073                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1074                 
1075                 /**
1076                   These _register calls are for the built-in
1077                   Charm .ci files, like arrays and load balancing.
1078                   If you add a .ci file to charm, you'll have to 
1079                   add a call to the _register routine here, or make
1080                   your library into a "-module".
1081                 */
1082                 _registerCkFutures();
1083                 _registerCkArray();
1084                 _registerLBDatabase();
1085                 _registerCkCallback();
1086                 _registertempo();
1087                 _registerwaitqd();
1088                 _registercharisma();
1089                 _registerCkCheckpoint();
1090 #if CMK_MEM_CHECKPOINT
1091                 _registerCkMemCheckpoint();
1092 #endif
1093
1094
1095                 /*
1096                   Setup Control Point Automatic Tuning Framework.
1097
1098                   By default it is enabled as a part of charm, 
1099                   however it won't enable its tracing module 
1100                   unless a +CPEnableMeasurements command line argument
1101                   is specified. See trace-common.C for more info
1102
1103                   Thus there should be no noticable overhead to 
1104                   always having the control point framework linked
1105                   in.
1106                   
1107                 */
1108 #if CMK_WITH_CONTROLPOINT
1109                 _registerPathHistory();
1110                 _registerControlPoints();
1111                 _registerTraceControlPoints();
1112 #endif
1113
1114
1115                 /**
1116                   CkRegisterMainModule is generated by the (unique)
1117                   "mainmodule" .ci file.  It will include calls to 
1118                   register all the .ci files.
1119                 */
1120                 CkRegisterMainModule();
1121
1122                 /**
1123                   _registerExternalModules is actually generated by 
1124                   charmc at link time (as "moduleinit<pid>.C").  
1125                   
1126                   This generated routine calls the _register functions
1127                   for the .ci files of libraries linked using "-module".
1128                   This funny initialization is most useful for AMPI/FEM
1129                   programs, which don't have a .ci file and hence have
1130                   no other way to control the _register process.
1131                 */
1132                 _registerExternalModules(argv);
1133                 
1134                 _registerDone();
1135         }
1136         /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1137         if (CkMyRank() == 0) {
1138           CpdBreakPointInit();
1139         }
1140         CmiNodeAllBarrier();
1141
1142         // Execute the initcalls registered in modules
1143         _initCallTable.enumerateInitCalls();
1144
1145 #if CMK_CHARMDEBUG
1146         CpdFinishInitialization();
1147 #endif
1148
1149         //CmiNodeAllBarrier();
1150
1151         CkpvAccess(_myStats) = new Stats();
1152         CkpvAccess(_msgPool) = new MsgPool();
1153
1154         CmiNodeAllBarrier();
1155 #if CMK_SMP_TRACE_COMMTHREAD
1156         _TRACE_BEGIN_COMPUTATION();     
1157 #else
1158         if (!inCommThread) {
1159           _TRACE_BEGIN_COMPUTATION();
1160         }
1161 #endif
1162
1163 #ifdef ADAPT_SCHED_MEM
1164     if(CkMyRank()==0){
1165         memCriticalEntries = new int[numMemCriticalEntries];
1166         int memcnt=0;
1167         for(int i=0; i<_entryTable.size(); i++){
1168             if(_entryTable[i]->isMemCritical){
1169                 memCriticalEntries[memcnt++] = i;
1170             }
1171         }
1172     }
1173 #endif
1174
1175 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1176     _messageLoggingInit();
1177 #endif
1178
1179 #ifndef __BLUEGENE__
1180         /*
1181                 FAULT_EVAC
1182         */
1183         CpvAccess(_validProcessors) = new char[CkNumPes()];
1184         for(int vProc=0;vProc<CkNumPes();vProc++){
1185                 CpvAccess(_validProcessors)[vProc]=1;
1186         }
1187         CpvAccess(startedEvac) = 0;
1188         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
1189         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
1190 #endif
1191         CpvAccess(serializer) = 0;
1192
1193         evacuate = 0;
1194         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1195 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
1196     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1197 #endif
1198
1199         if(_raiseEvac){
1200                 processRaiseEvacFile(_raiseEvacFile);
1201                 /*
1202                 if(CkMyPe() == 2){
1203                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1204                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1205                 }
1206                 if(CkMyPe() == 3){
1207                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1208                 }*/
1209         }       
1210
1211     if (!_replaySystem) {
1212         if (faultFunc == NULL) {         // this is not restart
1213             // these two are blocking calls for non-bigsim
1214 #if ! CMK_BLUEGENE_CHARM
1215           CmiInitCPUAffinity(argv);
1216           CmiInitMemAffinity(argv);
1217 #endif
1218         }
1219         CmiInitCPUTopology(argv);
1220     }
1221     //CldCallback();
1222 #if CMK_BLUEGENE_CHARM && CMK_CHARMDEBUG
1223       // Register the BG handler for CCS. Notice that this is put into a variable shared by
1224       // the whole real processor. This because converse needs to find it. We check that all
1225       // virtual processors register the same index for this handler.
1226     CpdBgInit();
1227 #endif
1228
1229         if (faultFunc) {
1230                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1231                 if (!inCommThread) {
1232                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1233                   msg->argc = CmiGetArgc(argv);
1234                   msg->argv = argv;
1235                   faultFunc(_restartDir, msg);
1236                   CkFreeMsg(msg);
1237                 }
1238         }else if(CkMyPe()==0){
1239                 _allStats = new Stats*[CkNumPes()];
1240                 register size_t i, nMains=_mainTable.size();
1241                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1242                 {
1243                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1244                         register void *obj = malloc(size);
1245                         _MEMCHECK(obj);
1246                         _mainTable[i]->setObj(obj);
1247                         CkpvAccess(_currentChare) = obj;
1248                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1249                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1250                         msg->argc = CmiGetArgc(argv);
1251                         msg->argv = argv;
1252                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1253 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1254             CpvAccess(_currentObj) = (Chare *)obj;
1255 #endif
1256                 }
1257                 _mainDone = 1;
1258
1259                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1260                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1261
1262
1263
1264
1265                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1266                 {
1267                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1268                         if(roMsg==0)
1269                                 continue;
1270                         //Pack the message and send it to all other processors
1271                         register envelope *env = UsrToEnv(roMsg);
1272                         env->setSrcPe(CkMyPe());
1273                         env->setMsgtype(ROMsgMsg);
1274                         env->setRoIdx(i);
1275                         CmiSetHandler(env, _initHandlerIdx);
1276                         CkPackMessage(&env);
1277                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1278                         CpvAccess(_qd)->create(CkNumPes()-1);
1279
1280                         //For processor 0, unpack and re-set the global
1281                         CkUnpackMessage(&env);
1282                         _processROMsgMsg(env);
1283                         _numInitMsgs++;
1284                 }
1285
1286                 //Determine the size of the RODataMessage
1287                 PUP::sizer ps;
1288                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1289
1290                 //Allocate and fill out the RODataMessage
1291                 envelope *env = _allocEnv(RODataMsg, ps.size());
1292                 PUP::toMem pp((char *)EnvToUsr(env));
1293                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1294
1295                 env->setCount(++_numInitMsgs);
1296                 env->setSrcPe(CkMyPe());
1297                 CmiSetHandler(env, _initHandlerIdx);
1298                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1299                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1300                 CpvAccess(_qd)->create(CkNumPes()-1);
1301                 _initDone();
1302         }
1303
1304         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1305         // when I am a communication thread, I don't participate initDone.
1306         if (inCommThread) {
1307                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1308                                         CkpvAccess(_coreState));
1309                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1310 ,
1311                                         CkpvAccess(_coreState));
1312         }
1313
1314 #if CMK_CHARMDEBUG
1315         // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1316        if (CpvAccess(cpdSuspendStartup))
1317        { 
1318           //CmiPrintf("In Parallel Debugging mode .....\n");
1319           CpdFreeze();
1320        }
1321 #endif
1322
1323
1324 #if __FAULT__
1325         if(killFlag){                                                  
1326                 readKillFile();                                        
1327         }
1328 #endif
1329
1330 }
1331
1332 // this is needed because on o2k, f90 programs have to have main in
1333 // fortran90.
1334 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1335 {
1336   int i;
1337   char **argv = new char*[*argc+2];
1338
1339   for(i=0;i <= *argc;i++) {
1340     if (length[i] < 100) {
1341       _argv[i][length[i]]='\0';
1342       argv[i] = &(_argv[i][0]);
1343     } else {
1344       argv[i][0] = '\0';
1345     }
1346   }
1347   argv[*argc+1]=0;
1348
1349   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1350 }
1351
1352 // user callable function to register an exit function, this function
1353 // will perform task of collecting of info from all pes to pe0, and call
1354 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1355 // see trace-summary for an example.
1356 void registerExitFn(CkExitFn fn)
1357 {
1358   _CkExitFnVec.enq(fn);
1359 }
1360
1361 /*@}*/