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