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