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