A few bug fixes related to the mlogft machine.
[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 _registerExternalModules(char **argv);
649 extern void _ckModuleInit(void);
650 extern void _loadbalancerInit();
651 #if CMK_MEM_CHECKPOINT
652 extern void init_memcheckpt(char **argv);
653 #endif
654 extern "C" void initCharmProjections();
655 extern "C" void CmiInitCPUTopology(char **argv);
656 extern "C" void CmiInitCPUAffinity(char **argv);
657
658 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
659 {
660   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
661   else _initCallTable.initProcCalls.enq(fn);
662 }
663
664 void InitCallTable::enumerateInitCalls()
665 {
666   int i;
667 #ifdef __BLUEGENE__
668   if(BgNodeRank()==0)        // called only once on an emulating node
669 #else
670   if(CkMyRank()==0) 
671 #endif
672   {
673     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
674   }
675   // initproc may depend on initnode calls.
676   CmiNodeAllBarrier();
677   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
678 }
679
680 CpvCExtern(int, cmiArgDebugFlag);
681 extern "C" void CpdFreeze(void);
682
683 extern "C" void initQd()
684 {
685         CpvInitialize(QdState*, _qd);
686         CpvAccess(_qd) = new QdState();
687         if (CmiMyRank() == 0) {
688 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
689         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
690 #endif
691         }
692         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
693 }
694
695 /**
696   This is the main charm setup routine.  It's called
697   on all processors after Converse initialization.
698   This routine gets passed to Converse from "main.C".
699   
700   The main purpose of this routine is to set up the objects
701   and Ckpv's used during a regular Charm run.  See the comment
702   at the top of the file for overall flow.
703 */
704 void _initCharm(int unused_argc, char **argv)
705
706         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
707
708         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
709
710         CkpvInitialize(PtrQ*,_buffQ);
711         CkpvInitialize(PtrVec*,_bocInitVec);
712         CkpvInitialize(void*, _currentChare);
713         CkpvInitialize(int,   _currentChareType);
714         CkpvInitialize(CkGroupID, _currentGroup);
715         CkpvInitialize(void *, _currentNodeGroupObj);
716         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
717         CkpvInitialize(GroupTable*, _groupTable);
718         CkpvInitialize(GroupIDTable*, _groupIDTable);
719         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
720         CkpvInitialize(UInt, _numGroups);
721         CkpvInitialize(int, _numInitsRecd);
722         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
723         CkpvInitialize(MsgPool*, _msgPool);
724         CkpvInitialize(CkCoreState *, _coreState);
725         /*
726                 Added for evacuation-sayantan
727         */
728 #ifndef __BLUEGENE__
729         CpvInitialize(char *,_validProcessors);
730         CpvInitialize(char ,startedEvac);
731 #endif
732         CpvInitialize(int,serializer);
733
734         CksvInitialize(UInt, _numNodeGroups);
735         CksvInitialize(GroupTable*, _nodeGroupTable);
736         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
737         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
738         CksvInitialize(CmiNodeLock, _nodeLock);
739         CksvInitialize(PtrVec*,_nodeBocInitVec);
740         CksvInitialize(UInt,_numInitNodeMsgs);
741         CkpvInitialize(int,_charmEpoch);
742         CkpvAccess(_charmEpoch)=0;
743
744         CkpvInitialize(_CkOutStream*, _ckout);
745         CkpvInitialize(_CkErrStream*, _ckerr);
746         CkpvInitialize(Stats*, _myStats);
747
748         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
749         CkpvAccess(_groupTable) = new GroupTable;
750         CkpvAccess(_groupTable)->init();
751         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
752         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
753         CkpvAccess(_buffQ) = new PtrQ();
754         CkpvAccess(_bocInitVec) = new PtrVec();
755
756         CkpvAccess(_currentNodeGroupObj) = NULL;
757
758         if(CkMyRank()==0)
759         {
760                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
761                 CksvAccess(_numInitNodeMsgs) = 0;
762                 CksvAccess(_nodeLock) = CmiCreateLock();
763                 CksvAccess(_nodeGroupTable) = new GroupTable();
764                 CksvAccess(_nodeGroupTable)->init();
765                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
766                 CksvAccess(_nodeBocInitVec) = new PtrVec();
767         }
768
769         CmiNodeAllBarrier();
770
771 #if ! CMK_BLUEGENE_CHARM
772         initQd();
773 #endif
774
775         CkpvAccess(_coreState)=new CkCoreState();
776
777         CkpvAccess(_numInitsRecd) = -1;  /*0;*/
778
779         CkpvAccess(_ckout) = new _CkOutStream();
780         CkpvAccess(_ckerr) = new _CkErrStream();
781
782         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
783         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
784         _roHandlerIdx = CkRegisterHandler((CmiHandler)_roHandler);
785         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
786         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
787         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
788         _nodeBocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
789         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
790         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
791         _ckModuleInit();
792
793         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
794
795         _futuresModuleInit(); // part of futures implementation is a converse module
796         _loadbalancerInit();
797         
798 #if CMK_MEM_CHECKPOINT
799         init_memcheckpt(argv);
800 #endif
801
802         initCharmProjections();
803 #if CMK_TRACE_IN_CHARM
804         // initialize trace module in ck
805         traceCharmInit(argv);
806 #endif
807         
808         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
809         
810         /**
811           The rank-0 processor of each node calls the 
812           translator-generated "_register" routines. 
813           
814           _register routines call the charm.h "CkRegister*" routines,
815           which record function pointers and class information for
816           all Charm entities, like Chares, Arrays, and readonlies.
817           
818           There's one _register routine generated for each
819           .ci file.  _register routines *must* be called in the 
820           same order on every node, and *must not* be called by 
821           multiple threads simultaniously.
822         */
823 #ifdef __BLUEGENE__
824         if(BgNodeRank()==0) 
825 #else
826         if(CkMyRank()==0)
827 #endif
828         {
829                 CmiArgGroup("Charm++",NULL);
830                 _parseCommandLineOpts(argv);
831                 _registerInit();
832                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
833                 CkRegisterChareInCharm(CkRegisterChare("null", 0));
834                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare));
835                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
836                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group));
837         CkRegisterChareInCharm(CkIndex_Group::__idx);
838                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
839                 
840                 /**
841                   These _register calls are for the built-in
842                   Charm .ci files, like arrays and load balancing.
843                   If you add a .ci file to charm, you'll have to 
844                   add a call to the _register routine here, or make
845                   your library into a "-module".
846                 */
847                 _registerCkFutures();
848                 _registerCkArray();
849                 _registerLBDatabase();
850                 _registerCkCallback();
851                 _registertempo();
852                 _registerwaitqd();
853                 _registercharisma();
854                 _registerCkCheckpoint();
855 #if CMK_MEM_CHECKPOINT
856                 _registerCkMemCheckpoint();
857 #endif
858                 
859                 /**
860                   _registerExternalModules is actually generated by 
861                   charmc at link time (as "moduleinit<pid>.C").  
862                   
863                   This generated routine calls the _register functions
864                   for the .ci files of libraries linked using "-module".
865                   This funny initialization is most useful for AMPI/FEM
866                   programs, which don't have a .ci file and hence have
867                   no other way to control the _register process.
868                 */
869                 _registerExternalModules(argv);
870                 
871                 /**
872                   CkRegisterMainModule is generated by the (unique)
873                   "mainmodule" .ci file.  It will include calls to 
874                   register all the .ci files.
875                 */
876                 CkRegisterMainModule();
877                 _registerDone();
878         }
879         CmiNodeAllBarrier();
880
881     // Execute the initcalls registered in modules
882         _initCallTable.enumerateInitCalls();
883
884 #ifndef CMK_OPTIMIZE
885 #ifdef __BLUEGENE__
886         if(BgNodeRank()==0)
887 #else
888         if(CkMyRank()==0)
889 #endif
890           CpdFinishInitialization();
891 #endif
892
893         //CmiNodeAllBarrier();
894
895         CkpvAccess(_myStats) = new Stats();
896         CkpvAccess(_msgPool) = new MsgPool();
897
898         CmiNodeAllBarrier();
899
900         if (!inCommThread) {
901           _TRACE_BEGIN_COMPUTATION();
902         }
903
904 #ifdef _FAULT_MLOG_
905     _messageLoggingInit();
906 #endif
907
908 #ifndef __BLUEGENE__
909         /*
910                 FAULT_EVAC
911         */
912         CpvAccess(_validProcessors) = new char[CkNumPes()];
913         for(int vProc=0;vProc<CkNumPes();vProc++){
914                 CpvAccess(_validProcessors)[vProc]=1;
915         }
916         CpvAccess(startedEvac) = 0;
917         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
918         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
919 #endif
920         CpvAccess(serializer) = 0;
921
922         evacuate = 0;
923         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
924 #ifdef _FAULT_MLOG_ 
925     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
926 #endif
927
928         if(_raiseEvac){
929                 processRaiseEvacFile(_raiseEvacFile);
930                 /*
931                 if(CkMyPe() == 2){
932                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
933                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
934                 }
935                 if(CkMyPe() == 3){
936                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
937                 }*/
938         }       
939         
940 #if ! CMK_BLUEGENE_CHARM
941         if (faultFunc == NULL) {         // this is not restart
942             // blocking calls
943           CmiInitCPUAffinity(argv);
944           CmiInitCPUTopology(argv);
945         }
946 #endif
947
948         if (faultFunc) {
949                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
950                 if (!inCommThread) {
951                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
952                   msg->argc = CmiGetArgc(argv);
953                   msg->argv = argv;
954                   faultFunc(_restartDir, msg);
955                   CkFreeMsg(msg);
956                 }
957         }else if(CkMyPe()==0){
958                 _allStats = new Stats*[CkNumPes()];
959                 register size_t i, nMains=_mainTable.size();
960                 for(i=0;i<nMains;i++)  /* Create all mainchares */
961                 {
962                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
963                         register void *obj = malloc(size);
964                         _MEMCHECK(obj);
965                         _mainTable[i]->setObj(obj);
966                         CkpvAccess(_currentChare) = obj;
967                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
968                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
969                         msg->argc = CmiGetArgc(argv);
970                         msg->argv = argv;
971                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
972 #ifdef _FAULT_MLOG_
973             CpvAccess(_currentObj) = (Chare *)obj;
974 #endif
975                 }
976                 _mainDone = 1;
977
978                 _STATS_RECORD_CREATE_CHARE_N(nMains);
979                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
980
981
982
983
984                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
985                 {
986                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
987                         if(roMsg==0)
988                                 continue;
989                         //Pack the message and send it to all other processors
990                         register envelope *env = UsrToEnv(roMsg);
991                         env->setSrcPe(CkMyPe());
992                         env->setMsgtype(ROMsgMsg);
993                         env->setRoIdx(i);
994                         CmiSetHandler(env, _initHandlerIdx);
995                         CkPackMessage(&env);
996                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
997                         CpvAccess(_qd)->create(CkNumPes()-1);
998
999                         //For processor 0, unpack and re-set the global
1000                         CkUnpackMessage(&env);
1001                         _processROMsgMsg(env);
1002                         _numInitMsgs++;
1003                 }
1004
1005                 //Determine the size of the RODataMessage
1006                 PUP::sizer ps;
1007                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1008
1009                 //Allocate and fill out the RODataMessage
1010                 envelope *env = _allocEnv(RODataMsg, ps.size());
1011                 PUP::toMem pp((char *)EnvToUsr(env));
1012                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1013
1014                 env->setCount(++_numInitMsgs);
1015                 env->setSrcPe(CkMyPe());
1016                 CmiSetHandler(env, _initHandlerIdx);
1017                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1018                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1019                 CpvAccess(_qd)->create(CkNumPes()-1);
1020                 _initDone();
1021         }
1022
1023         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1024         // when I am a communication thread, I don't participate initDone.
1025         if (inCommThread) {
1026                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1027                                         CkpvAccess(_coreState));
1028                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1029 ,
1030                                         CkpvAccess(_coreState));
1031         }
1032
1033 #if CMK_CCS_AVAILABLE
1034        if (CpvAccess(cmiArgDebugFlag))
1035        { 
1036           //CmiPrintf("In Parallel Debugging mode .....\n");
1037           CpdFreeze();
1038        }
1039 #endif
1040
1041
1042 #if __FAULT__
1043         if(killFlag){                                                  
1044                 readKillFile();                                        
1045         }
1046 #endif
1047
1048 }
1049
1050 // this is needed because on o2k, f90 programs have to have main in
1051 // fortran90.
1052 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1053 {
1054   int i;
1055   char **argv = new char*[*argc+2];
1056
1057   for(i=0;i <= *argc;i++) {
1058     if (length[i] < 100) {
1059       _argv[i][length[i]]='\0';
1060       argv[i] = &(_argv[i][0]);
1061     } else {
1062       argv[i][0] = '\0';
1063     }
1064   }
1065   argv[*argc+1]=0;
1066
1067   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1068 }
1069
1070 // user callable function to register an exit function, this function
1071 // will perform task of collecting of info from all pes to pe0, and call
1072 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1073 // see trace-summary for an example.
1074 void registerExitFn(CkExitFn fn)
1075 {
1076   _CkExitFnVec.enq(fn);
1077 }
1078
1079 /*@}*/