f3d8d6c96d801b9d18497d9b755ce54b25e1cf94
[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 Possible race conditions abound during this process,
36 which is probably overly complex.
37 */
38 /*@{*/
39
40 #include "ck.h"
41 #include "trace.h"
42
43 void CkRestartMain(const char* dirname);
44
45 #define  DEBUGF(x)     //CmiPrintf x;
46
47 #ifdef CALCULATE_HOPS
48 /** Turn on manually if you want to calculate hops from within Charm++
49 for some application **/
50
51 #include "TopoManager.h"
52
53 TopoManager *tmgr = NULL;
54 double hops = 0;
55
56 extern "C" void calculateTotalHops(int pe1, int pe2, int size) {
57   if(tmgr == NULL)
58     tmgr = new TopoManager();
59   hops += (tmgr->getHopsBetweenRanks(pe1, pe2) * size);
60 }
61
62 extern "C" void printTotalHops() {
63   CmiPrintf("TOTAL HOPS %lf\n", hops/(1024*1024) );
64 }
65 #endif
66
67 UChar _defaultQueueing = CK_QUEUEING_FIFO;
68
69 UInt  _printCS = 0;
70 UInt  _printSS = 0;
71
72 UInt  _numExpectInitMsgs = 0;
73 UInt  _numInitMsgs = 0;
74 CksvDeclare(UInt,_numInitNodeMsgs);
75 int   _infoIdx;
76 int   _charmHandlerIdx;
77 int   _initHandlerIdx;
78 int   _roHandlerIdx;
79 int   _roRestartHandlerIdx;
80 int   _bocHandlerIdx;
81 int   _nodeBocHandlerIdx;
82 int   _qdHandlerIdx;
83 int   _qdCommHandlerIdx;
84 int   _triggerHandlerIdx;
85 int   _mainDone = 0;
86 static int   _triggersSent = 0;
87
88 CkOutStream ckout;
89 CkErrStream ckerr;
90 CkInStream  ckin;
91
92 CkpvDeclare(void*,       _currentChare);
93 CkpvDeclare(int,         _currentChareType);
94 CkpvDeclare(CkGroupID,   _currentGroup);
95 CkpvDeclare(void*,       _currentNodeGroupObj);
96 CkpvDeclare(CkGroupID,   _currentGroupRednMgr);
97 CkpvDeclare(GroupTable*, _groupTable);
98 CkpvDeclare(GroupIDTable*, _groupIDTable);
99 CkpvDeclare(CmiImmediateLockType, _groupTableImmLock);
100 CkpvDeclare(UInt, _numGroups);
101
102 CkpvDeclare(CkCoreState *, _coreState);
103
104 CksvDeclare(UInt, _numNodeGroups);
105 CksvDeclare(GroupTable*, _nodeGroupTable);
106 CksvDeclare(GroupIDTable, _nodeGroupIDTable);
107 CksvDeclare(CmiImmediateLockType, _nodeGroupTableImmLock);
108 CksvDeclare(CmiNodeLock, _nodeLock);
109 CksvStaticDeclare(PtrVec*,_nodeBocInitVec);
110 CkpvDeclare(int, _charmEpoch);
111
112 CkpvDeclare(Stats*, _myStats);
113 CkpvDeclare(MsgPool*, _msgPool);
114
115 CkpvDeclare(_CkOutStream*, _ckout);
116 CkpvDeclare(_CkErrStream*, _ckerr);
117
118 CkpvStaticDeclare(int,  _numInitsRecd); /* UInt changed to int */
119 CkpvStaticDeclare(PtrQ*, _buffQ);
120 CkpvStaticDeclare(PtrVec*, _bocInitVec);
121
122 #ifndef CMK_CHARE_USE_PTR
123 CpvExtern(CkVec<void *>, chare_objs);
124 CpvExtern(CkVec<VidBlock *>, vidblocks);
125 #endif
126
127 /*
128         FAULT_EVAC
129 */
130 CpvDeclare(char *, _validProcessors);
131 CpvDeclare(char ,startedEvac);
132
133 int    _exitHandlerIdx;
134
135 static Stats** _allStats = 0;
136
137 static int   _numStatsRecd = 0;
138 static int   _exitStarted = 0;
139
140 static InitCallTable _initCallTable;
141
142 #ifndef CMK_OPTIMIZE
143 #define _STATS_ON(x) (x) = 1
144 #else
145 #define _STATS_ON(x) \
146           CmiPrintf("stats unavailable in optimized version. ignoring...\n");
147 #endif
148
149 // fault tolerance
150 typedef void (*CkFtFn)(const char *, CkArgMsg *);
151 static CkFtFn  faultFunc = NULL;
152 static char* _restartDir;
153
154 #ifdef _FAULT_MLOG_
155 int chkptPeriod=1000;
156 bool parallelRestart=false;
157 extern int BUFFER_TIME; //time spent waiting for buffered messages
158 #endif
159
160 // flag for killing processes 
161 extern int killFlag;
162 // file specifying the processes to be killed
163 extern char *killFile;
164 // function for reading the kill file
165 void readKillFile();
166
167
168 int _defaultObjectQ = 0;            // for obejct queue
169 int _ringexit = 0;                  // for charm exit
170 int _ringtoken = 8;
171
172
173 /*
174         FAULT_EVAC
175
176         flag which marks whether or not to trigger the processor shutdowns
177 */
178 static int _raiseEvac=0;
179 static char *_raiseEvacFile;
180 void processRaiseEvacFile(char *raiseEvacFile);
181
182 static inline void _parseCommandLineOpts(char **argv)
183 {
184   if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
185       _STATS_ON(_printCS);
186   if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
187       _STATS_ON(_printSS);
188   if (CmiGetArgFlagDesc(argv,"+fifo", "Default to FIFO queuing"))
189       _defaultQueueing = CK_QUEUEING_FIFO;
190   if (CmiGetArgFlagDesc(argv,"+lifo", "Default to LIFO queuing"))
191       _defaultQueueing = CK_QUEUEING_LIFO;
192   if (CmiGetArgFlagDesc(argv,"+ififo", "Default to integer-prioritized FIFO queuing"))
193       _defaultQueueing = CK_QUEUEING_IFIFO;
194   if (CmiGetArgFlagDesc(argv,"+ilifo", "Default to integer-prioritized LIFO queuing"))
195       _defaultQueueing = CK_QUEUEING_ILIFO;
196   if (CmiGetArgFlagDesc(argv,"+bfifo", "Default to bitvector-prioritized FIFO queuing"))
197       _defaultQueueing = CK_QUEUEING_BFIFO;
198   if (CmiGetArgFlagDesc(argv,"+blifo", "Default to bitvector-prioritized LIFO queuing"))
199       _defaultQueueing = CK_QUEUEING_BLIFO;
200   if (CmiGetArgFlagDesc(argv,"+objq", "Default to use object queue for every obejct"))
201   {
202 #if CMK_OBJECT_QUEUE_AVAILABLE
203       _defaultObjectQ = 1;
204       if (CkMyPe()==0)
205         CmiPrintf("Charm++> Create object queue for every Charm object.\n");
206 #else
207       CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
208 #endif
209   }
210   if(CmiGetArgString(argv,"+restart",&_restartDir))
211       faultFunc = CkRestartMain;
212 #if __FAULT__
213   if (CmiGetArgFlagDesc(argv,"+restartaftercrash","restarting this processor after a crash")){  
214 # if CMK_MEM_CHECKPOINT
215       faultFunc = CkMemRestart;
216 # endif
217 #ifdef _FAULT_MLOG_
218             faultFunc = CkMlogRestart;
219 #endif
220       CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
221   }
222   // reading the killFile
223   if(CmiGetArgStringDesc(argv,"+killFile", &killFile,"Generates SIGKILL on specified processors")){
224     if(faultFunc == NULL){
225       //do not read the killfile if this is a restarting processor
226       killFlag = 1;
227       if(CmiMyPe() == 0){
228         printf("[%d] killFlag set to 1 for file %s\n",CkMyPe(),killFile);
229       }
230     }
231   }
232 #endif
233
234   // shut down program in ring fashion to allow projections output w/o IO error
235   if (CmiGetArgIntDesc(argv,"+ringexit",&_ringtoken, "Program exits in a ring fashion")) 
236   {
237     _ringexit = 1;
238     if (CkMyPe()==0)
239       CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
240     if (_ringtoken > CkNumPes())  _ringtoken = CkNumPes();
241   }
242         /*
243                 FAULT_EVAC
244
245                 if the argument +raiseevac is present then cause faults
246         */
247         if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
248                 _raiseEvac = 1;
249         }
250 #ifdef _FAULT_MLOG_
251     if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
252         chkptPeriod = 100;
253     }
254     if(CmiGetArgFlagDesc(argv,"+Parallelrestart", "Parallel Restart with message logging protocol")){
255         parallelRestart = true;
256     }
257     if(!CmiGetArgIntDesc(argv,"+mlog_local_buffer",&_maxBufferedMessages,"# of local messages buffered in the message logging protoocl")){
258         _maxBufferedMessages = 2;
259     }
260     if(!CmiGetArgIntDesc(argv,"+mlog_remote_buffer",&_maxBufferedTicketRequests,"# of remote ticket requests buffered in the message logging protoocl")){
261         _maxBufferedTicketRequests = 2;
262     }
263     if(!CmiGetArgIntDesc(argv,"+mlog_buffer_time",&BUFFER_TIME,"# Time spent waiting for messages to be buffered in the message logging protoocl")){
264         BUFFER_TIME = 2;
265     }
266
267 #endif  
268         /* Anytime migration flag */
269         isAnytimeMigration = CmiTrue;
270         if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
271           isAnytimeMigration = CmiFalse;
272         }
273 }
274
275 static void _bufferHandler(void *msg)
276 {
277   DEBUGF(("[%d] _bufferHandler called.\n", CkMyPe()));
278   CkpvAccess(_buffQ)->enq(msg);
279 }
280
281 static void _discardHandler(envelope *env)
282 {
283   DEBUGF(("[%d] _discardHandler called.\n", CkMyPe()));
284   CmiFree(env);
285 }
286
287 #ifndef CMK_OPTIMIZE
288 static inline void _printStats(void)
289 {
290   DEBUGF(("[%d] _printStats\n", CkMyPe()));
291   int i;
292   if(_printSS || _printCS) {
293     Stats *total = new Stats();
294     _MEMCHECK(total);
295     for(i=0;i<CkNumPes();i++)
296       total->combine(_allStats[i]);
297     CkPrintf("Charm Kernel Summary Statistics:\n");
298     for(i=0;i<CkNumPes();i++) {
299       CkPrintf("Proc %d: [%d created, %d processed]\n", i,
300                _allStats[i]->getCharesCreated(),
301                _allStats[i]->getCharesProcessed());
302     }
303     CkPrintf("Total Chares: [%d created, %d processed]\n",
304              total->getCharesCreated(), total->getCharesProcessed());
305   }
306   if(_printCS) {
307     CkPrintf("Charm Kernel Detailed Statistics (R=requested P=processed):\n\n");
308
309     CkPrintf("         Create    Mesgs     Create    Mesgs     Create    Mesgs\n");
310     CkPrintf("         Chare     for       Group     for       Nodegroup for\n");
311     CkPrintf("PE   R/P Mesgs     Chares    Mesgs     Groups    Mesgs     Nodegroups\n");
312     CkPrintf("---- --- --------- --------- --------- --------- --------- ----------\n");
313
314     for(i=0;i<CkNumPes();i++) {
315       CkPrintf("%4d  R  %9d %9d %9d %9d %9d %9d\n      P  %9d %9d %9d %9d %9d %9d\n",i,
316                _allStats[i]->getCharesCreated(),
317                _allStats[i]->getForCharesCreated(),
318                _allStats[i]->getGroupsCreated(),
319                _allStats[i]->getGroupMsgsCreated(),
320                _allStats[i]->getNodeGroupsCreated(),
321                _allStats[i]->getNodeGroupMsgsCreated(),
322                _allStats[i]->getCharesProcessed(),
323                _allStats[i]->getForCharesProcessed(),
324                _allStats[i]->getGroupsProcessed(),
325                _allStats[i]->getGroupMsgsProcessed(),
326                _allStats[i]->getNodeGroupsProcessed(),
327                _allStats[i]->getNodeGroupMsgsProcessed());
328     }
329   }
330 }
331 #else
332 static inline void _printStats(void) {}
333 #endif
334
335 static inline void _sendStats(void)
336 {
337   DEBUGF(("[%d] _sendStats\n", CkMyPe()));
338 #ifndef CMK_OPTIMIZE
339   envelope *env = UsrToEnv(CkpvAccess(_myStats));
340 #else
341   envelope *env = _allocEnv(StatMsg);
342 #endif
343   env->setSrcPe(CkMyPe());
344   CmiSetHandler(env, _exitHandlerIdx);
345   CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
346 }
347
348 #ifdef _FAULT_MLOG_
349 extern void _messageLoggingExit();
350 #endif
351
352 static void _exitHandler(envelope *env)
353 {
354   DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
355   switch(env->getMsgtype()) {
356     case ExitMsg:
357       CkAssert(CkMyPe()==0);
358       if(_exitStarted) {
359         CmiFree(env);
360         return;
361       }
362       _exitStarted = 1;
363       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
364       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
365       CkNumberHandler(_nodeBocHandlerIdx, (CmiHandler)_discardHandler);
366       env->setMsgtype(ReqStatMsg);
367       env->setSrcPe(CkMyPe());
368       // if exit in ring, instead of broadcasting, send in ring
369       if (_ringexit){
370         DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
371         const int stride = CkNumPes()/_ringtoken;
372         int pe = 0;
373         while (pe<CkNumPes()) {
374           CmiSyncSend(pe, env->getTotalsize(), (char *)env);
375           pe += stride;
376         }
377         CmiFree(env);
378       }else{
379         CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
380       } 
381       break;
382     case ReqStatMsg:
383 #ifdef _FAULT_MLOG_
384         _messageLoggingExit();
385 #endif
386       DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
387       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
388       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
389       CkNumberHandler(_nodeBocHandlerIdx, (CmiHandler)_discardHandler);
390         /*FAULT_EVAC*/
391       if(CmiNodeAlive(CkMyPe())){
392          _sendStats();
393       } 
394       _mainDone = 1; // This is needed because the destructors for
395                      // readonly variables will be called when the program
396                      // exits. If the destructor is called while _mainDone
397                      // is 0, it will assume that the readonly variable was
398                      // declared locally. On all processors other than 0, 
399                      // _mainDone is never set to 1 before the program exits.
400 #ifndef CMK_OPTIMIZE
401       if (_ringexit) traceClose();
402 #endif
403       if (_ringexit) {
404         int stride = CkNumPes()/_ringtoken;
405         int pe = CkMyPe()+1;
406         if (pe < CkNumPes() && pe % stride != 0)
407           CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
408         else
409           CmiFree(env);
410       }
411       else
412         CmiFree(env);
413       if(CkMyPe()){
414         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
415         ConverseExit();
416       } 
417       break;
418     case StatMsg:
419       CkAssert(CkMyPe()==0);
420 #ifndef CMK_OPTIMIZE
421       _allStats[env->getSrcPe()] = (Stats*) EnvToUsr(env);
422 #endif
423       _numStatsRecd++;
424       DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), _numStatsRecd));
425                         /*FAULT_EVAC*/
426       if(_numStatsRecd==CkNumValidPes()) {
427         _printStats();
428         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
429         ConverseExit();
430       }
431       break;
432     default:
433       CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
434   }
435 }
436
437 static inline void _processBufferedBocInits(void)
438 {
439   CkCoreState *ck = CkpvAccess(_coreState);
440   CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler, ck);
441   register int i = 0;
442   PtrVec &inits=*CkpvAccess(_bocInitVec);
443   register int len = inits.size();
444   for(i=0; i<len; i++) {
445     envelope *env = inits[i];
446     if(env==0) continue;
447     if(env->isPacked())
448       CkUnpackMessage(&env);
449     _processBocInitMsg(ck,env);
450   }
451   delete &inits;
452 }
453
454 static inline void _processBufferedNodeBocInits(void)
455 {
456   CkCoreState *ck = CkpvAccess(_coreState);
457   CkNumberHandlerEx(_nodeBocHandlerIdx,(CmiHandlerEx)_processHandler,ck);
458   register int i = 0;
459   PtrVec &inits=*CksvAccess(_nodeBocInitVec);
460   register int len = inits.size();
461   for(i=0; i<len; i++) {
462     envelope *env = inits[i];
463     if(env==0) continue;
464     if(env->isPacked())
465       CkUnpackMessage(&env);
466     _processNodeBocInitMsg(ck,env);
467   }
468   delete &inits;
469 }
470
471 static inline void _processBufferedMsgs(void)
472 {
473   CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler,
474         CkpvAccess(_coreState));
475   envelope *env;
476   while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
477     if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
478       if(env->isForAnyPE())
479         CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
480       else
481         CmiSyncSendAndFree(CkMyPe(), env->getTotalsize(), (char *)env);
482     } else {
483       CmiSyncSendAndFree(CkMyPe(), env->getTotalsize(), (char *)env);
484     }
485   }
486 }
487
488 static int _charmLoadEstimator(void)
489 {
490   return CkpvAccess(_buffQ)->length();
491 }
492
493 static void _sendTriggers(void)
494 {
495   int i, num, first;
496   CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
497   if (_triggersSent == 0)
498   {
499     _triggersSent++;
500     num = CmiMyNodeSize();
501     register envelope *env = _allocEnv(RODataMsg);
502     env->setSrcPe(CkMyPe());
503     CmiSetHandler(env, _triggerHandlerIdx);
504     first = CmiNodeFirst(CmiMyNode());
505     for (i=0; i < num; i++)
506       if(first+i != CkMyPe())
507         CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
508     CmiFree(env);
509   }
510   CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
511 }
512
513 void _initDone(void)
514 {
515   DEBUGF(("[%d] _initDone.\n", CkMyPe()));
516   if (!_triggersSent) _sendTriggers();
517   CkNumberHandler(_triggerHandlerIdx, (CmiHandler)_discardHandler);
518   CmiNodeBarrier();
519   if(CkMyRank() == 0) {
520     _processBufferedNodeBocInits();
521   }
522   CmiNodeBarrier(); // wait for all nodegroups to be created
523   _processBufferedBocInits();
524   DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
525   CmiNodeBarrier();
526   DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
527   _processBufferedMsgs();
528   CkpvAccess(_charmEpoch)=1;
529 }
530
531 static void _triggerHandler(envelope *env)
532 {
533   if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
534   {
535     DEBUGF(("Calling Init Done from _triggerHandler\n"));
536     _initDone();
537   }
538   CmiFree(env);
539 }
540
541 static inline void _processROMsgMsg(envelope *env)
542 {
543   *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
544 }
545
546 static inline void _processRODataMsg(envelope *env)
547 {
548   //Unpack each readonly:
549   PUP::fromMem pu((char *)EnvToUsr(env));
550   for(size_t i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pu);
551   CmiFree(env);
552 }
553
554 static void _roRestartHandler(void *msg)
555 {
556   CkAssert(CkMyPe()!=0);
557   register envelope *env = (envelope *) msg;
558   CkpvAccess(_numInitsRecd)++;
559   _numExpectInitMsgs = env->getCount();
560   _processRODataMsg(env);
561 }
562
563 static void _roHandler(void *msg)
564 {
565   CpvAccess(_qd)->process();
566   _roRestartHandler(msg);
567 }
568
569 static void _initHandler(void *msg)
570 {
571   CkAssert(CkMyPe()!=0);
572   register envelope *env = (envelope *) msg;
573   switch (env->getMsgtype()) {
574     case BocInitMsg:
575       if (env->getGroupEpoch()==0)
576         CkpvAccess(_numInitsRecd)++;
577       CpvAccess(_qd)->process();
578       CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
579       break;
580     case NodeBocInitMsg:
581       CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
582       if (env->getGroupEpoch()==0)
583         CksvAccess(_numInitNodeMsgs)++;
584       CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
585       CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
586       CpvAccess(_qd)->process();
587       break;
588     case ROMsgMsg:
589       CkpvAccess(_numInitsRecd)++;
590       CpvAccess(_qd)->process();
591       if(env->isPacked()) CkUnpackMessage(&env);
592       _processROMsgMsg(env);
593       break;
594     case RODataMsg:
595       CkpvAccess(_numInitsRecd)++;
596       CpvAccess(_qd)->process();
597       _numExpectInitMsgs = env->getCount();
598       _processRODataMsg(env);
599       break;
600     default:
601       CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
602   }
603         DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
604   if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
605     _initDone();
606   }
607 }
608
609 // CkExit: start the termination process, but
610 //   then drop into the scheduler so the user's
611 //   method never returns (which would be confusing).
612 extern "C"
613 void _CkExit(void) 
614 {
615   // Shuts down Converse handlers for the upper layers on this processor
616   //
617   CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
618   CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
619   CkNumberHandler(_nodeBocHandlerIdx, (CmiHandler)_discardHandler);
620   DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
621
622   if(CkMyPe()==0) {
623     if(_exitStarted)
624       CsdScheduler(-1);
625     envelope *env = _allocEnv(ReqStatMsg);
626     env->setSrcPe(CkMyPe());
627     CmiSetHandler(env, _exitHandlerIdx);
628                 /*FAULT_EVAC*/
629     CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
630   } else {
631     envelope *env = _allocEnv(ExitMsg);
632     env->setSrcPe(CkMyPe());
633     CmiSetHandler(env, _exitHandlerIdx);
634     CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
635   }
636 #if ! CMK_BLUEGENE_THREAD
637   _TRACE_END_EXECUTE();
638   //Wait for stats, which will call ConverseExit when finished:
639   CsdScheduler(-1);
640 #endif
641 }
642
643 CkQ<CkExitFn> _CkExitFnVec;
644
645 // wrapper of CkExit
646 // traverse _CkExitFnVec to call registered user exit functions
647 // CkExitFn will call CkExit() when finished to make sure other
648 // registered functions get called.
649 extern "C"
650 void CkExit(void)
651 {
652         /*FAULT_EVAC*/
653         DEBUGF(("[%d] CkExit called \n",CkMyPe()));
654   if (!_CkExitFnVec.isEmpty()) {
655     CkExitFn fn = _CkExitFnVec.deq();
656     fn();
657   }
658   else
659     _CkExit();
660 }
661
662 /* This is a routine called in case the application is closing due to a signal.
663    Tear down structures that must be cleaned up even when unclean exit happens.
664    It is called by the machine layer whenever some problem occurs (it is thus up
665    to the machine layer to call this function). */
666 extern "C"
667 void EmergencyExit(void) {
668 #ifndef __BLUEGENE__
669   /* Delete _coreState to force any CkMessageWatcher to close down. */
670   delete CkpvAccess(_coreState);
671 #endif
672 }
673
674 static void _nullFn(void *, void *)
675 {
676   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
677 }
678
679 extern void _registerLBDatabase(void);
680 extern void _registerPathHistory(void);
681 extern void _registerExternalModules(char **argv);
682 extern void _ckModuleInit(void);
683 extern void _loadbalancerInit();
684 #if CMK_MEM_CHECKPOINT
685 extern void init_memcheckpt(char **argv);
686 #endif
687 extern "C" void initCharmProjections();
688 extern "C" void CmiInitCPUTopology(char **argv);
689 extern "C" void CmiInitCPUAffinity(char **argv);
690
691 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
692 {
693   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
694   else _initCallTable.initProcCalls.enq(fn);
695 }
696
697 void InitCallTable::enumerateInitCalls()
698 {
699   int i;
700 #ifdef __BLUEGENE__
701   if(BgNodeRank()==0)        // called only once on an emulating node
702 #else
703   if(CkMyRank()==0) 
704 #endif
705   {
706     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
707   }
708   // initproc may depend on initnode calls.
709   CmiNodeAllBarrier();
710   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
711 }
712
713 CpvCExtern(int, cpdSuspendStartup);
714 extern "C" void CpdFreeze(void);
715
716 extern int _dummy_dq;
717
718 extern "C" void initQd(char **argv)
719 {
720         CpvInitialize(QdState*, _qd);
721         CpvAccess(_qd) = new QdState();
722         if (CmiMyRank() == 0) {
723 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
724         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
725 #endif
726         }
727         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
728         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
729         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
730           if (CmiMyPe()==0)
731             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
732         }
733 }
734
735 /**
736   This is the main charm setup routine.  It's called
737   on all processors after Converse initialization.
738   This routine gets passed to Converse from "main.C".
739   
740   The main purpose of this routine is to set up the objects
741   and Ckpv's used during a regular Charm run.  See the comment
742   at the top of the file for overall flow.
743 */
744 void _initCharm(int unused_argc, char **argv)
745
746         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
747
748         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
749
750         CkpvInitialize(PtrQ*,_buffQ);
751         CkpvInitialize(PtrVec*,_bocInitVec);
752         CkpvInitialize(void*, _currentChare);
753         CkpvInitialize(int,   _currentChareType);
754         CkpvInitialize(CkGroupID, _currentGroup);
755         CkpvInitialize(void *, _currentNodeGroupObj);
756         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
757         CkpvInitialize(GroupTable*, _groupTable);
758         CkpvInitialize(GroupIDTable*, _groupIDTable);
759         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
760         CkpvInitialize(UInt, _numGroups);
761         CkpvInitialize(int, _numInitsRecd);
762         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
763         CkpvInitialize(MsgPool*, _msgPool);
764         CkpvInitialize(CkCoreState *, _coreState);
765         /*
766                 Added for evacuation-sayantan
767         */
768 #ifndef __BLUEGENE__
769         CpvInitialize(char *,_validProcessors);
770         CpvInitialize(char ,startedEvac);
771 #endif
772         CpvInitialize(int,serializer);
773
774 #ifndef CMK_CHARE_USE_PTR
775           /* chare and vidblock table */
776         CpvInitialize(CkVec<void *>, chare_objs);
777         CpvInitialize(CkVec<VidBlock *>, vidblocks);
778 #endif
779
780         CksvInitialize(UInt, _numNodeGroups);
781         CksvInitialize(GroupTable*, _nodeGroupTable);
782         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
783         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
784         CksvInitialize(CmiNodeLock, _nodeLock);
785         CksvInitialize(PtrVec*,_nodeBocInitVec);
786         CksvInitialize(UInt,_numInitNodeMsgs);
787         CkpvInitialize(int,_charmEpoch);
788         CkpvAccess(_charmEpoch)=0;
789
790         CkpvInitialize(_CkOutStream*, _ckout);
791         CkpvInitialize(_CkErrStream*, _ckerr);
792         CkpvInitialize(Stats*, _myStats);
793
794         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
795         CkpvAccess(_groupTable) = new GroupTable;
796         CkpvAccess(_groupTable)->init();
797         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
798         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
799         CkpvAccess(_buffQ) = new PtrQ();
800         CkpvAccess(_bocInitVec) = new PtrVec();
801
802         CkpvAccess(_currentNodeGroupObj) = NULL;
803
804         if(CkMyRank()==0)
805         {
806                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
807                 CksvAccess(_numInitNodeMsgs) = 0;
808                 CksvAccess(_nodeLock) = CmiCreateLock();
809                 CksvAccess(_nodeGroupTable) = new GroupTable();
810                 CksvAccess(_nodeGroupTable)->init();
811                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
812                 CksvAccess(_nodeBocInitVec) = new PtrVec();
813         }
814
815         CkCallbackInit();
816         
817         CmiNodeAllBarrier();
818
819 #if ! CMK_BLUEGENE_CHARM
820         initQd(argv);         // bigsim calls it in ConverseCommonInit
821 #endif
822
823         CkpvAccess(_coreState)=new CkCoreState();
824
825         CkpvAccess(_numInitsRecd) = 0;
826
827         CkpvAccess(_ckout) = new _CkOutStream();
828         CkpvAccess(_ckerr) = new _CkErrStream();
829
830         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
831         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
832         _roHandlerIdx = CkRegisterHandler((CmiHandler)_roHandler);
833         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
834         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
835         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
836         _nodeBocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
837         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
838         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
839         _ckModuleInit();
840
841         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
842
843         _futuresModuleInit(); // part of futures implementation is a converse module
844         _loadbalancerInit();
845         
846 #if CMK_MEM_CHECKPOINT
847         init_memcheckpt(argv);
848 #endif
849
850         initCharmProjections();
851 #if CMK_TRACE_IN_CHARM
852         // initialize trace module in ck
853         traceCharmInit(argv);
854 #endif
855         
856     CkpvInitialize(int, envelopeEventID);
857     CkpvAccess(envelopeEventID) = 0;
858         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
859         
860         /**
861           The rank-0 processor of each node calls the 
862           translator-generated "_register" routines. 
863           
864           _register routines call the charm.h "CkRegister*" routines,
865           which record function pointers and class information for
866           all Charm entities, like Chares, Arrays, and readonlies.
867           
868           There's one _register routine generated for each
869           .ci file.  _register routines *must* be called in the 
870           same order on every node, and *must not* be called by 
871           multiple threads simultaniously.
872         */
873 #ifdef __BLUEGENE__
874         if(BgNodeRank()==0) 
875 #else
876         if(CkMyRank()==0)
877 #endif
878         {
879                 CmiArgGroup("Charm++",NULL);
880                 _parseCommandLineOpts(argv);
881                 _registerInit();
882                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
883                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
884                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
885                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
886                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
887                 CkRegisterChareInCharm(CkIndex_Group::__idx);
888                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
889                 
890                 /**
891                   These _register calls are for the built-in
892                   Charm .ci files, like arrays and load balancing.
893                   If you add a .ci file to charm, you'll have to 
894                   add a call to the _register routine here, or make
895                   your library into a "-module".
896                 */
897                 _registerCkFutures();
898                 _registerCkArray();
899                 _registerLBDatabase();
900                 _registerCkCallback();
901                 _registertempo();
902                 _registerwaitqd();
903                 _registercharisma();
904                 _registerCkCheckpoint();
905 #if CMK_MEM_CHECKPOINT
906                 _registerCkMemCheckpoint();
907 #endif
908                 
909                 _registerPathHistory();
910
911                 /**
912                   _registerExternalModules is actually generated by 
913                   charmc at link time (as "moduleinit<pid>.C").  
914                   
915                   This generated routine calls the _register functions
916                   for the .ci files of libraries linked using "-module".
917                   This funny initialization is most useful for AMPI/FEM
918                   programs, which don't have a .ci file and hence have
919                   no other way to control the _register process.
920                 */
921                 _registerExternalModules(argv);
922                 
923                 /**
924                   CkRegisterMainModule is generated by the (unique)
925                   "mainmodule" .ci file.  It will include calls to 
926                   register all the .ci files.
927                 */
928                 CkRegisterMainModule();
929                 _registerDone();
930         }
931         CmiNodeAllBarrier();
932
933     // Execute the initcalls registered in modules
934         _initCallTable.enumerateInitCalls();
935
936 #ifndef CMK_OPTIMIZE
937 #ifdef __BLUEGENE__
938         if(BgNodeRank()==0)
939 #else
940         if(CkMyRank()==0)
941 #endif
942           CpdFinishInitialization();
943 #endif
944
945         //CmiNodeAllBarrier();
946
947         CkpvAccess(_myStats) = new Stats();
948         CkpvAccess(_msgPool) = new MsgPool();
949
950         CmiNodeAllBarrier();
951 #if CMK_SMP_TRACE_COMMTHREAD
952         _TRACE_BEGIN_COMPUTATION();     
953 #else
954         if (!inCommThread) {
955           _TRACE_BEGIN_COMPUTATION();
956         }
957 #endif
958
959 #ifdef ADAPT_SCHED_MEM
960     if(CkMyRank()==0){
961         memCriticalEntries = new int[numMemCriticalEntries];
962         int memcnt=0;
963         for(int i=0; i<_entryTable.size(); i++){
964             if(_entryTable[i]->isMemCritical){
965                 memCriticalEntries[memcnt++] = i;
966             }
967         }
968     }
969 #endif
970
971 #ifdef _FAULT_MLOG_
972     _messageLoggingInit();
973 #endif
974
975 #ifndef __BLUEGENE__
976         /*
977                 FAULT_EVAC
978         */
979         CpvAccess(_validProcessors) = new char[CkNumPes()];
980         for(int vProc=0;vProc<CkNumPes();vProc++){
981                 CpvAccess(_validProcessors)[vProc]=1;
982         }
983         CpvAccess(startedEvac) = 0;
984         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
985         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
986 #endif
987         CpvAccess(serializer) = 0;
988
989         evacuate = 0;
990         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
991 #ifdef _FAULT_MLOG_ 
992     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
993 #endif
994
995         if(_raiseEvac){
996                 processRaiseEvacFile(_raiseEvacFile);
997                 /*
998                 if(CkMyPe() == 2){
999                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1000                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1001                 }
1002                 if(CkMyPe() == 3){
1003                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1004                 }*/
1005         }       
1006         
1007         if (faultFunc == NULL) {         // this is not restart
1008             // these two are blocking calls for non-bigsim
1009 #if ! CMK_BLUEGENE_CHARM
1010           CmiInitCPUAffinity(argv);
1011 #endif
1012           CmiInitCPUTopology(argv);
1013         }
1014
1015         if (faultFunc) {
1016                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1017                 if (!inCommThread) {
1018                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1019                   msg->argc = CmiGetArgc(argv);
1020                   msg->argv = argv;
1021                   faultFunc(_restartDir, msg);
1022                   CkFreeMsg(msg);
1023                 }
1024         }else if(CkMyPe()==0){
1025                 _allStats = new Stats*[CkNumPes()];
1026                 register size_t i, nMains=_mainTable.size();
1027                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1028                 {
1029                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1030                         register void *obj = malloc(size);
1031                         _MEMCHECK(obj);
1032                         _mainTable[i]->setObj(obj);
1033                         CkpvAccess(_currentChare) = obj;
1034                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1035                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1036                         msg->argc = CmiGetArgc(argv);
1037                         msg->argv = argv;
1038                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1039 #ifdef _FAULT_MLOG_
1040             CpvAccess(_currentObj) = (Chare *)obj;
1041 #endif
1042                 }
1043                 _mainDone = 1;
1044
1045                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1046                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1047
1048
1049
1050
1051                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1052                 {
1053                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1054                         if(roMsg==0)
1055                                 continue;
1056                         //Pack the message and send it to all other processors
1057                         register envelope *env = UsrToEnv(roMsg);
1058                         env->setSrcPe(CkMyPe());
1059                         env->setMsgtype(ROMsgMsg);
1060                         env->setRoIdx(i);
1061                         CmiSetHandler(env, _initHandlerIdx);
1062                         CkPackMessage(&env);
1063                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1064                         CpvAccess(_qd)->create(CkNumPes()-1);
1065
1066                         //For processor 0, unpack and re-set the global
1067                         CkUnpackMessage(&env);
1068                         _processROMsgMsg(env);
1069                         _numInitMsgs++;
1070                 }
1071
1072                 //Determine the size of the RODataMessage
1073                 PUP::sizer ps;
1074                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1075
1076                 //Allocate and fill out the RODataMessage
1077                 envelope *env = _allocEnv(RODataMsg, ps.size());
1078                 PUP::toMem pp((char *)EnvToUsr(env));
1079                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1080
1081                 env->setCount(++_numInitMsgs);
1082                 env->setSrcPe(CkMyPe());
1083                 CmiSetHandler(env, _initHandlerIdx);
1084                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1085                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1086                 CpvAccess(_qd)->create(CkNumPes()-1);
1087                 _initDone();
1088         }
1089
1090         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1091         // when I am a communication thread, I don't participate initDone.
1092         if (inCommThread) {
1093                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1094                                         CkpvAccess(_coreState));
1095                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1096 ,
1097                                         CkpvAccess(_coreState));
1098         }
1099
1100 #if CMK_CCS_AVAILABLE
1101        if (CpvAccess(cpdSuspendStartup))
1102        { 
1103           //CmiPrintf("In Parallel Debugging mode .....\n");
1104           CpdFreeze();
1105        }
1106 #endif
1107
1108
1109 #if __FAULT__
1110         if(killFlag){                                                  
1111                 readKillFile();                                        
1112         }
1113 #endif
1114
1115 }
1116
1117 // this is needed because on o2k, f90 programs have to have main in
1118 // fortran90.
1119 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1120 {
1121   int i;
1122   char **argv = new char*[*argc+2];
1123
1124   for(i=0;i <= *argc;i++) {
1125     if (length[i] < 100) {
1126       _argv[i][length[i]]='\0';
1127       argv[i] = &(_argv[i][0]);
1128     } else {
1129       argv[i][0] = '\0';
1130     }
1131   }
1132   argv[*argc+1]=0;
1133
1134   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1135 }
1136
1137 // user callable function to register an exit function, this function
1138 // will perform task of collecting of info from all pes to pe0, and call
1139 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1140 // see trace-summary for an example.
1141 void registerExitFn(CkExitFn fn)
1142 {
1143   _CkExitFnVec.enq(fn);
1144 }
1145
1146 /*@}*/