Deleting a few handler never used
[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=0; i<len; i++) {
441     envelope *env = inits[i];
442     if(env==0) continue;
443     if(env->isPacked())
444       CkUnpackMessage(&env);
445     _processBocInitMsg(ck,env);
446   }
447   delete &inits;
448 }
449
450 static inline void _processBufferedNodeBocInits(void)
451 {
452   CkCoreState *ck = CkpvAccess(_coreState);
453   register int i = 0;
454   PtrVec &inits=*CksvAccess(_nodeBocInitVec);
455   register int len = inits.size();
456   for(i=0; i<len; i++) {
457     envelope *env = inits[i];
458     if(env==0) continue;
459     if(env->isPacked())
460       CkUnpackMessage(&env);
461     _processNodeBocInitMsg(ck,env);
462   }
463   delete &inits;
464 }
465
466 static inline void _processBufferedMsgs(void)
467 {
468   CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler,
469         CkpvAccess(_coreState));
470   envelope *env;
471   while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
472     if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
473       if(env->isForAnyPE())
474         CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
475       else
476         CmiSyncSendAndFree(CkMyPe(), env->getTotalsize(), (char *)env);
477     } else {
478       CmiSyncSendAndFree(CkMyPe(), env->getTotalsize(), (char *)env);
479     }
480   }
481 }
482
483 static int _charmLoadEstimator(void)
484 {
485   return CkpvAccess(_buffQ)->length();
486 }
487
488 static void _sendTriggers(void)
489 {
490   int i, num, first;
491   CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
492   if (_triggersSent == 0)
493   {
494     _triggersSent++;
495     num = CmiMyNodeSize();
496     register envelope *env = _allocEnv(RODataMsg);
497     env->setSrcPe(CkMyPe());
498     CmiSetHandler(env, _triggerHandlerIdx);
499     first = CmiNodeFirst(CmiMyNode());
500     for (i=0; i < num; i++)
501       if(first+i != CkMyPe())
502         CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
503     CmiFree(env);
504   }
505   CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
506 }
507
508 void _initDone(void)
509 {
510   DEBUGF(("[%d] _initDone.\n", CkMyPe()));
511   if (!_triggersSent) _sendTriggers();
512   CkNumberHandler(_triggerHandlerIdx, (CmiHandler)_discardHandler);
513   CmiNodeBarrier();
514   if(CkMyRank() == 0) {
515     _processBufferedNodeBocInits();
516   }
517   CmiNodeBarrier(); // wait for all nodegroups to be created
518   _processBufferedBocInits();
519   DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
520   CmiNodeBarrier();
521   DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
522   _processBufferedMsgs();
523   CkpvAccess(_charmEpoch)=1;
524 }
525
526 static void _triggerHandler(envelope *env)
527 {
528   if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
529   {
530     DEBUGF(("Calling Init Done from _triggerHandler\n"));
531     _initDone();
532   }
533   CmiFree(env);
534 }
535
536 static inline void _processROMsgMsg(envelope *env)
537 {
538   *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
539 }
540
541 static inline void _processRODataMsg(envelope *env)
542 {
543   //Unpack each readonly:
544   PUP::fromMem pu((char *)EnvToUsr(env));
545   for(size_t i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pu);
546   CmiFree(env);
547 }
548
549 static void _roRestartHandler(void *msg)
550 {
551   CkAssert(CkMyPe()!=0);
552   register envelope *env = (envelope *) msg;
553   CkpvAccess(_numInitsRecd)++;
554   _numExpectInitMsgs = env->getCount();
555   _processRODataMsg(env);
556 }
557
558 static void _initHandler(void *msg)
559 {
560   CkAssert(CkMyPe()!=0);
561   register envelope *env = (envelope *) msg;
562   switch (env->getMsgtype()) {
563     case BocInitMsg:
564       if (env->getGroupEpoch()==0)
565         CkpvAccess(_numInitsRecd)++;
566       CpvAccess(_qd)->process();
567       CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
568       break;
569     case NodeBocInitMsg:
570       CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
571       if (env->getGroupEpoch()==0)
572         CksvAccess(_numInitNodeMsgs)++;
573       CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
574       CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
575       CpvAccess(_qd)->process();
576       break;
577     case ROMsgMsg:
578       CkpvAccess(_numInitsRecd)++;
579       CpvAccess(_qd)->process();
580       if(env->isPacked()) CkUnpackMessage(&env);
581       _processROMsgMsg(env);
582       break;
583     case RODataMsg:
584       CkpvAccess(_numInitsRecd)++;
585       CpvAccess(_qd)->process();
586       _numExpectInitMsgs = env->getCount();
587       _processRODataMsg(env);
588       break;
589     default:
590       CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
591   }
592         DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
593   if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
594     _initDone();
595   }
596 }
597
598 // CkExit: start the termination process, but
599 //   then drop into the scheduler so the user's
600 //   method never returns (which would be confusing).
601 extern "C"
602 void _CkExit(void) 
603 {
604   // Shuts down Converse handlers for the upper layers on this processor
605   //
606   CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
607   CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
608   DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
609
610   if(CkMyPe()==0) {
611     if(_exitStarted)
612       CsdScheduler(-1);
613     envelope *env = _allocEnv(ReqStatMsg);
614     env->setSrcPe(CkMyPe());
615     CmiSetHandler(env, _exitHandlerIdx);
616                 /*FAULT_EVAC*/
617     CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
618   } else {
619     envelope *env = _allocEnv(ExitMsg);
620     env->setSrcPe(CkMyPe());
621     CmiSetHandler(env, _exitHandlerIdx);
622     CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
623   }
624 #if ! CMK_BLUEGENE_THREAD
625   _TRACE_END_EXECUTE();
626   //Wait for stats, which will call ConverseExit when finished:
627   CsdScheduler(-1);
628 #endif
629 }
630
631 CkQ<CkExitFn> _CkExitFnVec;
632
633 // wrapper of CkExit
634 // traverse _CkExitFnVec to call registered user exit functions
635 // CkExitFn will call CkExit() when finished to make sure other
636 // registered functions get called.
637 extern "C"
638 void CkExit(void)
639 {
640         /*FAULT_EVAC*/
641         DEBUGF(("[%d] CkExit called \n",CkMyPe()));
642   if (!_CkExitFnVec.isEmpty()) {
643     CkExitFn fn = _CkExitFnVec.deq();
644     fn();
645   }
646   else
647     _CkExit();
648 }
649
650 /* This is a routine called in case the application is closing due to a signal.
651    Tear down structures that must be cleaned up even when unclean exit happens.
652    It is called by the machine layer whenever some problem occurs (it is thus up
653    to the machine layer to call this function). */
654 extern "C"
655 void EmergencyExit(void) {
656 #ifndef __BLUEGENE__
657   /* Delete _coreState to force any CkMessageWatcher to close down. */
658   delete CkpvAccess(_coreState);
659 #endif
660 }
661
662 static void _nullFn(void *, void *)
663 {
664   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
665 }
666
667 extern void _registerLBDatabase(void);
668 extern void _registerPathHistory(void);
669 extern void _registerExternalModules(char **argv);
670 extern void _ckModuleInit(void);
671 extern void _loadbalancerInit();
672 #if CMK_MEM_CHECKPOINT
673 extern void init_memcheckpt(char **argv);
674 #endif
675 extern "C" void initCharmProjections();
676 extern "C" void CmiInitCPUTopology(char **argv);
677 extern "C" void CmiInitCPUAffinity(char **argv);
678
679 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
680 {
681   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
682   else _initCallTable.initProcCalls.enq(fn);
683 }
684
685 void InitCallTable::enumerateInitCalls()
686 {
687   int i;
688 #ifdef __BLUEGENE__
689   if(BgNodeRank()==0)        // called only once on an emulating node
690 #else
691   if(CkMyRank()==0) 
692 #endif
693   {
694     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
695   }
696   // initproc may depend on initnode calls.
697   CmiNodeAllBarrier();
698   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
699 }
700
701 CpvCExtern(int, cpdSuspendStartup);
702 extern "C" void CpdFreeze(void);
703
704 extern int _dummy_dq;
705
706 extern "C" void initQd(char **argv)
707 {
708         CpvInitialize(QdState*, _qd);
709         CpvAccess(_qd) = new QdState();
710         if (CmiMyRank() == 0) {
711 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
712         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
713 #endif
714         }
715         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
716         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
717         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
718           if (CmiMyPe()==0)
719             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
720         }
721 }
722
723 /**
724   This is the main charm setup routine.  It's called
725   on all processors after Converse initialization.
726   This routine gets passed to Converse from "main.C".
727   
728   The main purpose of this routine is to set up the objects
729   and Ckpv's used during a regular Charm run.  See the comment
730   at the top of the file for overall flow.
731 */
732 void _initCharm(int unused_argc, char **argv)
733
734         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
735
736         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
737
738         CkpvInitialize(PtrQ*,_buffQ);
739         CkpvInitialize(PtrVec*,_bocInitVec);
740         CkpvInitialize(void*, _currentChare);
741         CkpvInitialize(int,   _currentChareType);
742         CkpvInitialize(CkGroupID, _currentGroup);
743         CkpvInitialize(void *, _currentNodeGroupObj);
744         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
745         CkpvInitialize(GroupTable*, _groupTable);
746         CkpvInitialize(GroupIDTable*, _groupIDTable);
747         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
748         CkpvInitialize(UInt, _numGroups);
749         CkpvInitialize(int, _numInitsRecd);
750         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
751         CkpvInitialize(MsgPool*, _msgPool);
752         CkpvInitialize(CkCoreState *, _coreState);
753         /*
754                 Added for evacuation-sayantan
755         */
756 #ifndef __BLUEGENE__
757         CpvInitialize(char *,_validProcessors);
758         CpvInitialize(char ,startedEvac);
759 #endif
760         CpvInitialize(int,serializer);
761
762 #ifndef CMK_CHARE_USE_PTR
763           /* chare and vidblock table */
764         CpvInitialize(CkVec<void *>, chare_objs);
765         CpvInitialize(CkVec<VidBlock *>, vidblocks);
766 #endif
767
768         CksvInitialize(UInt, _numNodeGroups);
769         CksvInitialize(GroupTable*, _nodeGroupTable);
770         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
771         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
772         CksvInitialize(CmiNodeLock, _nodeLock);
773         CksvInitialize(PtrVec*,_nodeBocInitVec);
774         CksvInitialize(UInt,_numInitNodeMsgs);
775         CkpvInitialize(int,_charmEpoch);
776         CkpvAccess(_charmEpoch)=0;
777
778         CkpvInitialize(_CkOutStream*, _ckout);
779         CkpvInitialize(_CkErrStream*, _ckerr);
780         CkpvInitialize(Stats*, _myStats);
781
782         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
783         CkpvAccess(_groupTable) = new GroupTable;
784         CkpvAccess(_groupTable)->init();
785         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
786         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
787         CkpvAccess(_buffQ) = new PtrQ();
788         CkpvAccess(_bocInitVec) = new PtrVec();
789
790         CkpvAccess(_currentNodeGroupObj) = NULL;
791
792         if(CkMyRank()==0)
793         {
794                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
795                 CksvAccess(_numInitNodeMsgs) = 0;
796                 CksvAccess(_nodeLock) = CmiCreateLock();
797                 CksvAccess(_nodeGroupTable) = new GroupTable();
798                 CksvAccess(_nodeGroupTable)->init();
799                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
800                 CksvAccess(_nodeBocInitVec) = new PtrVec();
801         }
802
803         CkCallbackInit();
804         
805         CmiNodeAllBarrier();
806
807 #if ! CMK_BLUEGENE_CHARM
808         initQd(argv);         // bigsim calls it in ConverseCommonInit
809 #endif
810
811         CkpvAccess(_coreState)=new CkCoreState();
812
813         CkpvAccess(_numInitsRecd) = 0;
814
815         CkpvAccess(_ckout) = new _CkOutStream();
816         CkpvAccess(_ckerr) = new _CkErrStream();
817
818         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
819         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
820         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
821         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
822         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
823         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
824         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
825         _ckModuleInit();
826
827         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
828
829         _futuresModuleInit(); // part of futures implementation is a converse module
830         _loadbalancerInit();
831         
832 #if CMK_MEM_CHECKPOINT
833         init_memcheckpt(argv);
834 #endif
835
836         initCharmProjections();
837 #if CMK_TRACE_IN_CHARM
838         // initialize trace module in ck
839         traceCharmInit(argv);
840 #endif
841         
842     CkpvInitialize(int, envelopeEventID);
843     CkpvAccess(envelopeEventID) = 0;
844         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
845         
846         /**
847           The rank-0 processor of each node calls the 
848           translator-generated "_register" routines. 
849           
850           _register routines call the charm.h "CkRegister*" routines,
851           which record function pointers and class information for
852           all Charm entities, like Chares, Arrays, and readonlies.
853           
854           There's one _register routine generated for each
855           .ci file.  _register routines *must* be called in the 
856           same order on every node, and *must not* be called by 
857           multiple threads simultaniously.
858         */
859 #ifdef __BLUEGENE__
860         if(BgNodeRank()==0) 
861 #else
862         if(CkMyRank()==0)
863 #endif
864         {
865                 CmiArgGroup("Charm++",NULL);
866                 _parseCommandLineOpts(argv);
867                 _registerInit();
868                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
869                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
870                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
871                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
872                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
873                 CkRegisterChareInCharm(CkIndex_Group::__idx);
874                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
875                 
876                 /**
877                   These _register calls are for the built-in
878                   Charm .ci files, like arrays and load balancing.
879                   If you add a .ci file to charm, you'll have to 
880                   add a call to the _register routine here, or make
881                   your library into a "-module".
882                 */
883                 _registerCkFutures();
884                 _registerCkArray();
885                 _registerLBDatabase();
886                 _registerCkCallback();
887                 _registertempo();
888                 _registerwaitqd();
889                 _registercharisma();
890                 _registerCkCheckpoint();
891 #if CMK_MEM_CHECKPOINT
892                 _registerCkMemCheckpoint();
893 #endif
894                 
895                 _registerPathHistory();
896
897                 /**
898                   _registerExternalModules is actually generated by 
899                   charmc at link time (as "moduleinit<pid>.C").  
900                   
901                   This generated routine calls the _register functions
902                   for the .ci files of libraries linked using "-module".
903                   This funny initialization is most useful for AMPI/FEM
904                   programs, which don't have a .ci file and hence have
905                   no other way to control the _register process.
906                 */
907                 _registerExternalModules(argv);
908                 
909                 /**
910                   CkRegisterMainModule is generated by the (unique)
911                   "mainmodule" .ci file.  It will include calls to 
912                   register all the .ci files.
913                 */
914                 CkRegisterMainModule();
915                 _registerDone();
916         }
917         CmiNodeAllBarrier();
918
919     // Execute the initcalls registered in modules
920         _initCallTable.enumerateInitCalls();
921
922 #ifndef CMK_OPTIMIZE
923 #ifdef __BLUEGENE__
924         if(BgNodeRank()==0)
925 #else
926         if(CkMyRank()==0)
927 #endif
928           CpdFinishInitialization();
929 #endif
930
931         //CmiNodeAllBarrier();
932
933         CkpvAccess(_myStats) = new Stats();
934         CkpvAccess(_msgPool) = new MsgPool();
935
936         CmiNodeAllBarrier();
937 #if CMK_SMP_TRACE_COMMTHREAD
938         _TRACE_BEGIN_COMPUTATION();     
939 #else
940         if (!inCommThread) {
941           _TRACE_BEGIN_COMPUTATION();
942         }
943 #endif
944
945 #ifdef ADAPT_SCHED_MEM
946     if(CkMyRank()==0){
947         memCriticalEntries = new int[numMemCriticalEntries];
948         int memcnt=0;
949         for(int i=0; i<_entryTable.size(); i++){
950             if(_entryTable[i]->isMemCritical){
951                 memCriticalEntries[memcnt++] = i;
952             }
953         }
954     }
955 #endif
956
957 #ifdef _FAULT_MLOG_
958     _messageLoggingInit();
959 #endif
960
961 #ifndef __BLUEGENE__
962         /*
963                 FAULT_EVAC
964         */
965         CpvAccess(_validProcessors) = new char[CkNumPes()];
966         for(int vProc=0;vProc<CkNumPes();vProc++){
967                 CpvAccess(_validProcessors)[vProc]=1;
968         }
969         CpvAccess(startedEvac) = 0;
970         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
971         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
972 #endif
973         CpvAccess(serializer) = 0;
974
975         evacuate = 0;
976         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
977 #ifdef _FAULT_MLOG_ 
978     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
979 #endif
980
981         if(_raiseEvac){
982                 processRaiseEvacFile(_raiseEvacFile);
983                 /*
984                 if(CkMyPe() == 2){
985                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
986                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
987                 }
988                 if(CkMyPe() == 3){
989                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
990                 }*/
991         }       
992         
993         if (faultFunc == NULL) {         // this is not restart
994             // these two are blocking calls for non-bigsim
995 #if ! CMK_BLUEGENE_CHARM
996           CmiInitCPUAffinity(argv);
997 #endif
998           CmiInitCPUTopology(argv);
999         }
1000
1001         if (faultFunc) {
1002                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1003                 if (!inCommThread) {
1004                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1005                   msg->argc = CmiGetArgc(argv);
1006                   msg->argv = argv;
1007                   faultFunc(_restartDir, msg);
1008                   CkFreeMsg(msg);
1009                 }
1010         }else if(CkMyPe()==0){
1011                 _allStats = new Stats*[CkNumPes()];
1012                 register size_t i, nMains=_mainTable.size();
1013                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1014                 {
1015                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1016                         register void *obj = malloc(size);
1017                         _MEMCHECK(obj);
1018                         _mainTable[i]->setObj(obj);
1019                         CkpvAccess(_currentChare) = obj;
1020                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1021                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1022                         msg->argc = CmiGetArgc(argv);
1023                         msg->argv = argv;
1024                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1025 #ifdef _FAULT_MLOG_
1026             CpvAccess(_currentObj) = (Chare *)obj;
1027 #endif
1028                 }
1029                 _mainDone = 1;
1030
1031                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1032                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1033
1034
1035
1036
1037                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1038                 {
1039                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1040                         if(roMsg==0)
1041                                 continue;
1042                         //Pack the message and send it to all other processors
1043                         register envelope *env = UsrToEnv(roMsg);
1044                         env->setSrcPe(CkMyPe());
1045                         env->setMsgtype(ROMsgMsg);
1046                         env->setRoIdx(i);
1047                         CmiSetHandler(env, _initHandlerIdx);
1048                         CkPackMessage(&env);
1049                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1050                         CpvAccess(_qd)->create(CkNumPes()-1);
1051
1052                         //For processor 0, unpack and re-set the global
1053                         CkUnpackMessage(&env);
1054                         _processROMsgMsg(env);
1055                         _numInitMsgs++;
1056                 }
1057
1058                 //Determine the size of the RODataMessage
1059                 PUP::sizer ps;
1060                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1061
1062                 //Allocate and fill out the RODataMessage
1063                 envelope *env = _allocEnv(RODataMsg, ps.size());
1064                 PUP::toMem pp((char *)EnvToUsr(env));
1065                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1066
1067                 env->setCount(++_numInitMsgs);
1068                 env->setSrcPe(CkMyPe());
1069                 CmiSetHandler(env, _initHandlerIdx);
1070                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1071                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1072                 CpvAccess(_qd)->create(CkNumPes()-1);
1073                 _initDone();
1074         }
1075
1076         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1077         // when I am a communication thread, I don't participate initDone.
1078         if (inCommThread) {
1079                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1080                                         CkpvAccess(_coreState));
1081                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1082 ,
1083                                         CkpvAccess(_coreState));
1084         }
1085
1086 #if CMK_CCS_AVAILABLE
1087        if (CpvAccess(cpdSuspendStartup))
1088        { 
1089           //CmiPrintf("In Parallel Debugging mode .....\n");
1090           CpdFreeze();
1091        }
1092 #endif
1093
1094
1095 #if __FAULT__
1096         if(killFlag){                                                  
1097                 readKillFile();                                        
1098         }
1099 #endif
1100
1101 }
1102
1103 // this is needed because on o2k, f90 programs have to have main in
1104 // fortran90.
1105 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1106 {
1107   int i;
1108   char **argv = new char*[*argc+2];
1109
1110   for(i=0;i <= *argc;i++) {
1111     if (length[i] < 100) {
1112       _argv[i][length[i]]='\0';
1113       argv[i] = &(_argv[i][0]);
1114     } else {
1115       argv[i][0] = '\0';
1116     }
1117   }
1118   argv[*argc+1]=0;
1119
1120   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1121 }
1122
1123 // user callable function to register an exit function, this function
1124 // will perform task of collecting of info from all pes to pe0, and call
1125 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1126 // see trace-summary for an example.
1127 void registerExitFn(CkExitFn fn)
1128 {
1129   _CkExitFnVec.enq(fn);
1130 }
1131
1132 /*@}*/