charmxi cleanup: rename atomic construct to serial internally
[charm.git] / src / ck-core / init.C
blob95d685f2233256f8c98deac0b4f9f1ee7a99fdac
1 /**
2 \addtogroup CkInit
3 \brief Controls the Charm++ startup process.
5 This file runs the entire Charm++ startup process.
7 The process begins with every processor finishing the 
8 Converse startup process and calling _initCharm.
9 This routine runs almost the entire Charm++ setup process.
10 It begins by setting up various Cpvs and subsystems.
12 The rank 0 processor of each node then does
13 the Charm++ registration, by calling the various _register
14 routines.  
16 Now processor 0:
17 <ol>
18 <li>Creates each mainchare, by allocating the chares
19  and calling their constructors with argc/argv.
20  This typically results in a number of chare/group creations.
21 <li>Sends off all readonly data to the other processors.
22 </ol>
23 After _initCharm, processor 0 immediately begins work.
25 The other processors, however, must wait until they recieve 
26 the readonly data and all group creations.  They do this by 
27 setting the _charmHandlerIdx to a special "_bufferHandler"
28 which simply saves all normal messages into a special queue.  
30 As the startup data (readonlies and group creations) streams
31 into _initHandler, it counts messages until it is fully 
32 initialized, then calls _initDone to clean out the queues 
33 and resume normal operation.  
35 Upon resume of normal operation, the user code is guaranteed that
36 all readonlies (both data and messages) have been set consistently
37 on all processors, and that the constructors for all nodegroups
38 and groups allocated from a mainchare have been called.
40 It is not guaranteed the order in which (node)groups allocated
41 outside of a mainchare are constructed, nor that the construction
42 will happen before other messages have been delivered by the scheduler.
44 Even though not exposed to the final users, the creation order of
45 groups and nodegroups allocated in mainchares is deterministic and
46 respects the following points:
47 <ul>
48 <li>On all processors, there is no guarantee of the order of creation
49 between (node)groups allocated from different mainchares;
50 <li>On processor zero, within a mainchare, all (node)groups are created
51 in the order specified by the source code (strictly), including array
52 allocation of initial elements;
53 <li>On processors other than zero, within a mainchare, the order
54 specified by the source code is maintained between different nodegroups
55 and between different groups;
56 <li>On processors other than zero, the ordering between groups and
57 nodegroups is NOT maintained, as all nodegroups are created before any
58 group is created.
59 </ul>
61 This process should not have race conditions, but it can
62 never be excluded...
64 /*@{*/
66 #include "ckcheckpoint.h"
67 #include "ck.h"
68 #include "trace.h"
69 #include "CkCheckpoint.decl.h"
70 #include "ckmulticast.h"
71 #include <sstream>
72 #include <limits.h>
74 #if CMK_CUDA
75 #include "cuda-hybrid-api.h"
76 #endif
78 void CkRestartMain(const char* dirname, CkArgMsg* args);
80 #define  DEBUGF(x)     //CmiPrintf x;
82 #include "TopoManager.h"
84 UChar _defaultQueueing = CK_QUEUEING_FIFO;
86 UInt  _printCS = 0;
87 UInt  _printSS = 0;
89 /**
90  * This value has the number of total initialization message a processor awaits.
91  * It is received on nodes other than zero together with the ROData message.
92  * Even though it is shared by all processors it is ok: it doesn't matter when and
93  * by who it is set, provided that it becomes equal to the number of awaited messages
94  * (which is always at least one ---the readonly data message).
95  */
96 UInt  _numExpectInitMsgs = 0;
97 /**
98  * This number is used only by processor zero to count how many messages it will
99  * send out for the initialization process. After the readonly data message is sent
100  * (containing this counter), its value becomes irrelevant.
101  */
102 UInt  _numInitMsgs = 0;
104  * Count the number of nodegroups that have been created in mainchares.
105  * Since the nodegroup creation is executed by a single processor in a
106  * given node, this value must be seen by all processors in a node.
107  */
108 CksvDeclare(UInt,_numInitNodeMsgs);
109 int   _infoIdx;
110 int   _charmHandlerIdx;
111 int   _initHandlerIdx;
112 int   _roRestartHandlerIdx;
113 int   _bocHandlerIdx;
114 int   _qdHandlerIdx;
115 int   _qdCommHandlerIdx;
116 int   _triggerHandlerIdx;
117 bool  _mainDone = false;
118 CksvDeclare(bool, _triggersSent);
120 CkOutStream ckout;
121 CkErrStream ckerr;
122 CkInStream  ckin;
124 CkpvDeclare(void*,       _currentChare);
125 CkpvDeclare(int,         _currentChareType);
126 CkpvDeclare(CkGroupID,   _currentGroup);
127 CkpvDeclare(void*,       _currentNodeGroupObj);
128 CkpvDeclare(CkGroupID,   _currentGroupRednMgr);
129 CkpvDeclare(GroupTable*, _groupTable);
130 CkpvDeclare(GroupIDTable*, _groupIDTable);
131 CkpvDeclare(CmiImmediateLockType, _groupTableImmLock);
132 CkpvDeclare(UInt, _numGroups);
134 CkpvDeclare(CkCoreState *, _coreState);
136 CksvDeclare(UInt, _numNodeGroups);
137 CksvDeclare(GroupTable*, _nodeGroupTable);
138 CksvDeclare(GroupIDTable, _nodeGroupIDTable);
139 CksvDeclare(CmiImmediateLockType, _nodeGroupTableImmLock);
140 CksvDeclare(CmiNodeLock, _nodeLock);
141 CksvStaticDeclare(PtrVec*,_nodeBocInitVec);
142 CkpvDeclare(int, _charmEpoch);
144 CkpvDeclare(bool, _destroyingNodeGroup);
147 CkpvDeclare(Stats*, _myStats);
148 CkpvDeclare(MsgPool*, _msgPool);
150 CkpvDeclare(_CkOutStream*, _ckout);
151 CkpvDeclare(_CkErrStream*, _ckerr);
153 CkpvStaticDeclare(int,  _numInitsRecd);
154 CkpvStaticDeclare(bool,  _initdone);
155 CkpvStaticDeclare(PtrQ*, _buffQ);
156 CkpvStaticDeclare(PtrVec*, _bocInitVec);
158 //for interoperability
159 extern void _libExitHandler(envelope *env);
160 extern int _libExitHandlerIdx;
161 CpvCExtern(int,interopExitFlag);
163 #if CMK_SHRINK_EXPAND
164 //for shrink expand cleanup
165 int _ROGroupRestartHandlerIdx;
166 const char* _shrinkexpand_basedir;
167 #endif
169         FAULT_EVAC
171 CpvCExtern(char *, _validProcessors);
172 CkpvDeclare(char ,startedEvac);
174 int    _exitHandlerIdx;
176 #if CMK_WITH_STATS
177 static Stats** _allStats = 0;
178 #endif
179 static bool   _exitStarted = 0;
181 static InitCallTable _initCallTable;
183 #if CMK_WITH_STATS
184 #define _STATS_ON(x) (x) = 1
185 #else
186 #define _STATS_ON(x) \
187           if (CkMyPe()==0) CmiPrintf("stats unavailable in optimized version. ignoring...\n");
188 #endif
190 // fault tolerance
191 typedef void (*CkFtFn)(const char *, CkArgMsg *);
192 static CkFtFn  faultFunc = NULL;
193 static char* _restartDir;
195 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
196 int teamSize=1;
197 int chkptPeriod=1000;
198 bool fastRecovery = false;
199 int parallelRecovery = 1;
200 extern int BUFFER_TIME; //time spent waiting for buffered messages
201 #endif
203 // flag for killing processes 
204 extern bool killFlag;
205 // file specifying the processes to be killed
206 extern char *killFile;
207 // function for reading the kill file
208 void readKillFile();
209 #if CMK_MESSAGE_LOGGING
210 // flag for disk checkpoint
211 extern bool diskCkptFlag;
212 #endif
214 int _defaultObjectQ = 0;            // for obejct queue
215 bool _ringexit = 0;                 // for charm exit
216 int _ringtoken = 8;
217 extern int _messageBufferingThreshold;
221         FAULT_EVAC
223         flag which marks whether or not to trigger the processor shutdowns
225 static bool _raiseEvac=0;
226 static char *_raiseEvacFile;
227 void processRaiseEvacFile(char *raiseEvacFile);
229 extern bool useNodeBlkMapping;
231 extern "C" int quietMode;
232 extern "C" int quietModeRequested;
234 // Modules are required to register command line opts they will parse. These
235 // options are stored in the _optSet, and then when parsing command line opts
236 // users will be warned about options starting with a '+' that are not in this
237 // table. This usually implies that they are attempting to use a Charm++ option
238 // without having compiled Charm++ to use the module that options belongs to.
239 std::set<std::string> _optSet;
240 void _registerCommandLineOpt(const char* opt) {
241   // The command line options are only checked during init on PE0, so this makes
242   // thread safety easy.
243   if (CkMyPe() == 0) {
244     _optSet.insert(opt);
245   }
248 static inline void _parseCommandLineOpts(char **argv)
250   if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
251       _STATS_ON(_printCS);
252   if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
253       _STATS_ON(_printSS);
254   if (CmiGetArgFlagDesc(argv,"+fifo", "Default to FIFO queuing"))
255       _defaultQueueing = CK_QUEUEING_FIFO;
256   if (CmiGetArgFlagDesc(argv,"+lifo", "Default to LIFO queuing"))
257       _defaultQueueing = CK_QUEUEING_LIFO;
258   if (CmiGetArgFlagDesc(argv,"+ififo", "Default to integer-prioritized FIFO queuing"))
259       _defaultQueueing = CK_QUEUEING_IFIFO;
260   if (CmiGetArgFlagDesc(argv,"+ilifo", "Default to integer-prioritized LIFO queuing"))
261       _defaultQueueing = CK_QUEUEING_ILIFO;
262   if (CmiGetArgFlagDesc(argv,"+bfifo", "Default to bitvector-prioritized FIFO queuing"))
263       _defaultQueueing = CK_QUEUEING_BFIFO;
264   if (CmiGetArgFlagDesc(argv,"+blifo", "Default to bitvector-prioritized LIFO queuing"))
265       _defaultQueueing = CK_QUEUEING_BLIFO;
266   if (CmiGetArgFlagDesc(argv,"+objq", "Default to use object queue for every obejct"))
267   {
268 #if CMK_OBJECT_QUEUE_AVAILABLE
269       _defaultObjectQ = 1;
270       if (CkMyPe()==0)
271         CmiPrintf("Charm++> Create object queue for every Charm object.\n");
272 #else
273       CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
274 #endif
275   }
277 #if CMK_SHRINK_EXPAND
278   if (!CmiGetArgStringDesc(argv, "+shrinkexpand_basedir", (char **)&_shrinkexpand_basedir,
279                            "Checkpoint directory used for shrink-expand (defaults to /dev/shm)"))
280       _shrinkexpand_basedir = "/dev/shm";
281 #endif
283   if(CmiGetArgString(argv,"+restart",&_restartDir))
284       faultFunc = CkRestartMain;
285 #if __FAULT__
286   if (CmiGetArgIntDesc(argv,"+restartaftercrash",&CpvAccess(_curRestartPhase),"restarting this processor after a crash")){      
287 # if CMK_MEM_CHECKPOINT
288       faultFunc = CkMemRestart;
289 # endif
290 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
291       faultFunc = CkMlogRestart;
292 #endif
293       CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
294   }
295 #if CMK_MESSAGE_LOGGING
296         // reading +ftc_disk flag
297         if (CmiGetArgFlagDesc(argv, "+ftc_disk", "Disk Checkpointing")) {
298                 diskCkptFlag = true;
299     }
300 #endif
301   // reading the killFile
302   if(CmiGetArgStringDesc(argv,"+killFile", &killFile,"Generates SIGKILL on specified processors")){
303     if(faultFunc == NULL){
304       //do not read the killfile if this is a restarting processor
305       killFlag = true;
306       if(CmiMyPe() == 0){
307         printf("[%d] killFlag set to true for file %s\n",CkMyPe(),killFile);
308       }
309     }
310   }
311 #endif
313   // shut down program in ring fashion to allow projections output w/o IO error
314   if (CmiGetArgIntDesc(argv,"+ringexit",&_ringtoken, "Program exits in a ring fashion")) 
315   {
316     _ringexit = true;
317     if (CkMyPe()==0)
318       CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
319     if (_ringtoken > CkNumPes())  _ringtoken = CkNumPes();
320   }
321         /*
322                 FAULT_EVAC
324                 if the argument +raiseevac is present then cause faults
325         */
326         if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
327                 _raiseEvac = 1;
328         }
329 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
330         if(!CmiGetArgIntDesc(argv,"+teamSize",&teamSize,"Set the team size for message logging")){
331         teamSize = 1;
332     }
333     if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
334         chkptPeriod = 100;
335     }
336         if(CmiGetArgIntDesc(argv,"+fastRecovery", &parallelRecovery, "Parallel recovery with message logging protocol")){
337         fastRecovery = true;
338     }
339 #endif
341         if (!CmiGetArgIntDesc(argv, "+messageBufferingThreshold",
342                               &_messageBufferingThreshold,
343                               "Message size above which the runtime will buffer messages directed at unlocated array elements")) {
344           _messageBufferingThreshold = INT_MAX;
345         }
347         /* Anytime migration flag */
348         _isAnytimeMigration = true;
349         if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
350           _isAnytimeMigration = false;
351         }
352         
353         _isNotifyChildInRed = true;
354         if (CmiGetArgFlagDesc(argv,"+noNotifyChildInReduction","The program has at least one element per processor for each charm array created")) {
355           _isNotifyChildInRed = false;
356         }
358         _isStaticInsertion = false;
359         if (CmiGetArgFlagDesc(argv,"+staticInsertion","Array elements are only inserted at construction")) {
360           _isStaticInsertion = true;
361         }
363         useNodeBlkMapping = false;
364         if (CmiGetArgFlagDesc(argv,"+useNodeBlkMapping","Array elements are block-mapped in SMP-node level")) {
365           useNodeBlkMapping = true;
366         }
368 #if ! CMK_WITH_CONTROLPOINT
369         // Display a warning if charm++ wasn't compiled with control point support but user is expecting it
370         if( CmiGetArgFlag(argv,"+CPSamplePeriod") || 
371             CmiGetArgFlag(argv,"+CPSamplePeriodMs") || 
372             CmiGetArgFlag(argv,"+CPSchemeRandom") || 
373             CmiGetArgFlag(argv,"+CPExhaustiveSearch") || 
374             CmiGetArgFlag(argv,"+CPAlwaysUseDefaults") || 
375             CmiGetArgFlag(argv,"+CPSimulAnneal") || 
376             CmiGetArgFlag(argv,"+CPCriticalPathPrio") || 
377             CmiGetArgFlag(argv,"+CPBestKnown") || 
378             CmiGetArgFlag(argv,"+CPSteering") || 
379             CmiGetArgFlag(argv,"+CPMemoryAware") || 
380             CmiGetArgFlag(argv,"+CPSimplex") || 
381             CmiGetArgFlag(argv,"+CPDivideConquer") || 
382             CmiGetArgFlag(argv,"+CPLDBPeriod") || 
383             CmiGetArgFlag(argv,"+CPLDBPeriodLinear") || 
384             CmiGetArgFlag(argv,"+CPLDBPeriodQuadratic") || 
385             CmiGetArgFlag(argv,"+CPLDBPeriodOptimal") || 
386             CmiGetArgFlag(argv,"+CPDefaultValues") || 
387             CmiGetArgFlag(argv,"+CPGatherAll") || 
388             CmiGetArgFlag(argv,"+CPGatherMemoryUsage") || 
389             CmiGetArgFlag(argv,"+CPGatherUtilization") || 
390             CmiGetArgFlag(argv,"+CPSaveData") || 
391             CmiGetArgFlag(argv,"+CPNoFilterData") || 
392             CmiGetArgFlag(argv,"+CPLoadData") || 
393             CmiGetArgFlag(argv,"+CPDataFilename")    )
394           {         
395             CkAbort("You specified a control point command line argument, but compiled charm++ without control point support.\n");
396           }
397 #endif
398        
401 static void _bufferHandler(void *msg)
403   DEBUGF(("[%d] _bufferHandler called.\n", CkMyPe()));
404   CkpvAccess(_buffQ)->enq(msg);
407 static void _discardHandler(envelope *env)
409 //  MESSAGE_PHASE_CHECK(env);
411   DEBUGF(("[%d] _discardHandler called.\n", CkMyPe()));
412 #if CMK_MEM_CHECKPOINT
413   //CkPrintf("[%d] _discardHandler called!\n", CkMyPe());
414   if (CkInRestarting()) CpvAccess(_qd)->process();
415 #endif
416   CmiFree(env);
419 #if CMK_WITH_STATS
420 static inline void _printStats(void)
422   DEBUGF(("[%d] _printStats\n", CkMyPe()));
423   int i;
424   if(_printSS || _printCS) {
425     Stats *total = new Stats();
426     _MEMCHECK(total);
427     for(i=0;i<CkNumPes();i++)
428       total->combine(_allStats[i]);
429     CkPrintf("Charm Kernel Summary Statistics:\n");
430     for(i=0;i<CkNumPes();i++) {
431       CkPrintf("Proc %d: [%d created, %d processed]\n", i,
432                _allStats[i]->getCharesCreated(),
433                _allStats[i]->getCharesProcessed());
434     }
435     CkPrintf("Total Chares: [%d created, %d processed]\n",
436              total->getCharesCreated(), total->getCharesProcessed());
437   }
438   if(_printCS) {
439     CkPrintf("Charm Kernel Detailed Statistics (R=requested P=processed):\n\n");
441     CkPrintf("         Create    Mesgs     Create    Mesgs     Create    Mesgs\n");
442     CkPrintf("         Chare     for       Group     for       Nodegroup for\n");
443     CkPrintf("PE   R/P Mesgs     Chares    Mesgs     Groups    Mesgs     Nodegroups\n");
444     CkPrintf("---- --- --------- --------- --------- --------- --------- ----------\n");
446     for(i=0;i<CkNumPes();i++) {
447       CkPrintf("%4d  R  %9d %9d %9d %9d %9d %9d\n      P  %9d %9d %9d %9d %9d %9d\n",i,
448                _allStats[i]->getCharesCreated(),
449                _allStats[i]->getForCharesCreated(),
450                _allStats[i]->getGroupsCreated(),
451                _allStats[i]->getGroupMsgsCreated(),
452                _allStats[i]->getNodeGroupsCreated(),
453                _allStats[i]->getNodeGroupMsgsCreated(),
454                _allStats[i]->getCharesProcessed(),
455                _allStats[i]->getForCharesProcessed(),
456                _allStats[i]->getGroupsProcessed(),
457                _allStats[i]->getGroupMsgsProcessed(),
458                _allStats[i]->getNodeGroupsProcessed(),
459                _allStats[i]->getNodeGroupMsgsProcessed());
460     }
461   }
463 #else
464 static inline void _printStats(void) {}
465 #endif
467 typedef struct _statsHeader
469   int n;
470 } statsHeader;
472 static void * mergeStats(int *size, void *data, void **remote, int count)
474   envelope *newData;
475   statsHeader *dataMsg = (statsHeader*)EnvToUsr((envelope*) data), *newDataMsg;
476   int nPes = dataMsg->n, currentIndex = 0;
478   for (int i = 0; i < count; ++i)
479   {
480     nPes += ((statsHeader *)EnvToUsr((envelope *)remote[i]))->n;
481   }
483   newData = _allocEnv(StatMsg, sizeof(statsHeader) + sizeof(Stats)*nPes);
484   *size = newData->getTotalsize();
485   newDataMsg = (statsHeader *)EnvToUsr(newData);
486   newDataMsg->n = nPes;
488   statsHeader *current = dataMsg;
489   Stats *currentStats = (Stats*)(current + 1), *destination = (Stats*)(newDataMsg + 1);
490   memcpy(destination + currentIndex, currentStats, sizeof(Stats) * current->n);
491   currentIndex += current->n;
493   for (int i = 0; i < count; ++i)
494   {
495     current = ((statsHeader *)EnvToUsr((envelope *)remote[i]));
496     currentStats = (Stats *)(current + 1);
497     memcpy(destination + currentIndex, currentStats, sizeof(Stats) * current->n);
498     currentIndex += current->n;
499   }
501   CmiFree(data);
502   return newData;
505 static inline void _sendStats(void)
507   DEBUGF(("[%d] _sendStats\n", CkMyPe()));
508   envelope *env = _allocEnv(StatMsg, sizeof(statsHeader) + sizeof(Stats));
509   statsHeader* msg = (statsHeader*)EnvToUsr(env);
510   msg->n = 1;
511   memcpy(msg+1, CkpvAccess(_myStats), sizeof(Stats));
512   CmiSetHandler(env, _exitHandlerIdx);
513   CmiReduce(env, env->getTotalsize(), mergeStats);
516 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
517 extern void _messageLoggingExit();
518 #endif
520 #if __FAULT__
521 //CpvExtern(int, CldHandlerIndex);
522 //extern "C" void CldHandler(char *);
523 extern int index_skipCldHandler;
524 extern void _skipCldHandler(void *converseMsg);
526 void _discard_charm_message()
528   CkNumberHandler(_charmHandlerIdx,_discardHandler);
529 //  CkNumberHandler(CpvAccess(CldHandlerIndex), _discardHandler);
530   CkNumberHandler(index_skipCldHandler, _discardHandler);
533 void _resume_charm_message()
535   CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
536 //  CkNumberHandler(CpvAccess(CldHandlerIndex), CldHandler);
537   CkNumberHandler(index_skipCldHandler, _skipCldHandler);
539 #endif
541 static void _exitHandler(envelope *env)
543   DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
544   switch(env->getMsgtype()) {
545     case StartExitMsg:
546       CkAssert(CkMyPe()==0);
547       if (!_CkExitFnVec.isEmpty()) {
548         CkExitFn fn = _CkExitFnVec.deq();
549         fn();
550         break;
551       }
552       // else goto next
553     case ExitMsg:
554       CkAssert(CkMyPe()==0);
555       if(_exitStarted) {
556         CmiFree(env);
557         return;
558       }
559       _exitStarted = true;
560       CkNumberHandler(_charmHandlerIdx,_discardHandler);
561       CkNumberHandler(_bocHandlerIdx, _discardHandler);
562 #if !CMK_BIGSIM_THREAD
563       env->setMsgtype(ReqStatMsg);
564       env->setSrcPe(CkMyPe());
565       // if exit in ring, instead of broadcasting, send in ring
566       if (_ringexit){
567         DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
568         const int stride = CkNumPes()/_ringtoken;
569         int pe = 0;
570         while (pe<CkNumPes()) {
571           CmiSyncSend(pe, env->getTotalsize(), (char *)env);
572           pe += stride;
573         }
574         CmiFree(env);
575       }else{
576         CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
577       }
578 #else
579       CmiFree(env);
580       ConverseExit();
581 #endif
582       break;
583     case ReqStatMsg:
584 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
585       _messageLoggingExit();
586 #endif
587       DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
588       CkNumberHandler(_charmHandlerIdx,_discardHandler);
589       CkNumberHandler(_bocHandlerIdx, _discardHandler);
590       /*FAULT_EVAC*/
591       if(CmiNodeAlive(CkMyPe())){
592 #if CMK_WITH_STATS
593          _sendStats();
594 #endif
595       _mainDone = true; // This is needed because the destructors for
596                         // readonly variables will be called when the program
597                         // exits. If the destructor is called while _mainDone
598                         // is false, it will assume that the readonly variable was
599                         // declared locally. On all processors other than 0,
600                         // _mainDone is never set to true before the program exits.
601 #if CMK_TRACE_ENABLED
602       if (_ringexit) traceClose();
603 #endif
604     }
605       if (_ringexit) {
606         int stride = CkNumPes()/_ringtoken;
607         int pe = CkMyPe()+1;
608         if (pe < CkNumPes() && pe % stride != 0)
609           CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
610         else
611           CmiFree(env);
612       }
613       else
614         CmiFree(env);
615 #if CMK_SHRINK_EXPAND
616       ConverseCleanup();
617 #endif
618       //everyone exits here - there may be issues with leftover messages in the queue
619 #if !CMK_WITH_STATS
620       DEBUGF(("[%d] Calling converse exit from ReqStatMsg \n",CkMyPe()));
621       ConverseExit();
622       if(CharmLibInterOperate)
623         CpvAccess(interopExitFlag) = 1;
624 #endif
625       break;
626 #if CMK_WITH_STATS
627     case StatMsg:
628     {
629       CkAssert(CkMyPe()==0);
630       statsHeader* header = (statsHeader*)EnvToUsr(env);
631       int n = header->n;
632       Stats* currentStats = (Stats*)(header + 1);
633       for (int i = 0; i < n; ++i)
634       {
635         _allStats[currentStats->getPe()] = currentStats;
636         currentStats++;
637       }
638       DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), n));
639                         /*FAULT_EVAC*/
640       _printStats();
641       // broadcast to all others that they can now exit
642       envelope* env = _allocEnv(StatDoneMsg);
643       CmiSetHandler(env, _exitHandlerIdx);
644       CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char*)env);
645     }
646     break;
648     case StatDoneMsg:
649       DEBUGF(("[%d] Calling converse exit from StatDoneMsg \n",CkMyPe()));
650       ConverseExit();
651       if (CharmLibInterOperate)
652         CpvAccess(interopExitFlag) = 1;
653       break;
654 #endif
655     default:
656       CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
657   }
660 #if CMK_SHRINK_EXPAND
661 void _ROGroupRestartHandler(void * msg){
662   CkResumeRestartMain((char *)msg);
664 #endif
667  * Create all groups in this processor (not called on processor zero).
668  * Notice that only groups created in mainchares are processed here;
669  * groups created later are processed as regular messages.
670  */
671 static inline void _processBufferedBocInits(void)
673   CkCoreState *ck = CkpvAccess(_coreState);
674   CkNumberHandlerEx(_bocHandlerIdx,_processHandler, ck);
675   PtrVec &inits=*CkpvAccess(_bocInitVec);
676   int len = inits.size();
677   for(int i=1; i<len; i++) {
678     envelope *env = inits[i];
679     if(env==0) {
680 #if CMK_SHRINK_EXPAND
681       if(_inrestart){
682         CkPrintf("_processBufferedBocInits: empty message in restart, ignoring\n");
683         break;
684       }
685       else
686         CkAbort("_processBufferedBocInits: empty message");
687 #else
688       CkAbort("_processBufferedBocInits: empty message");
689 #endif
690     }
691     if(env->isPacked())
692       CkUnpackMessage(&env);
693     _processBocInitMsg(ck,env);
694   }
695   delete &inits;
699  * Create all nodegroups in this node (called only by rank zero, and never on node zero).
700  * Notice that only nodegroups created in mainchares are processed here;
701  * nodegroups created later are processed as regular messages.
702  */
703 static inline void _processBufferedNodeBocInits(void)
705   CkCoreState *ck = CkpvAccess(_coreState);
706   PtrVec &inits=*CksvAccess(_nodeBocInitVec);
707   int len = inits.size();
708   for(int i=1; i<len; i++) {
709     envelope *env = inits[i];
710     if(env==0) CkAbort("_processBufferedNodeBocInits: empty message");
711     if(env->isPacked())
712       CkUnpackMessage(&env);
713     _processNodeBocInitMsg(ck,env);
714   }
715   delete &inits;
718 static inline void _processBufferedMsgs(void)
720   CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
721   envelope *env;
722   while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
723     if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
724       if(env->isForAnyPE())
725         _CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
726       else
727         _processHandler((void *)env, CkpvAccess(_coreState));
728     } else {
729       _processHandler((void *)env, CkpvAccess(_coreState));
730     }
731   }
734 static int _charmLoadEstimator(void)
736   return CkpvAccess(_buffQ)->length();
740  * This function is used to send other processors on the same node a signal so
741  * they can check if their _initDone can be called: the reason for this is that
742  * the check at the end of _initHandler can fail due to a missing message containing
743  * a Nodegroup creation. When that message arrives only one processor will receive
744  * it, and thus if no notification is sent to the other processors in the node, they
745  * will never proceed.
746  */
747 static void _sendTriggers(void)
749   int i, num, first;
750   CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
751   if (!CksvAccess(_triggersSent))
752   {
753     CksvAccess(_triggersSent) = true;
754     num = CmiMyNodeSize();
755     envelope *env = _allocEnv(RODataMsg); // Notice that the type here is irrelevant
756     env->setSrcPe(CkMyPe());
757     CmiSetHandler(env, _triggerHandlerIdx);
758     first = CmiNodeFirst(CmiMyNode());
759     for (i=0; i < num; i++)
760       if(first+i != CkMyPe())
761         CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
762     CmiFree(env);
763   }
764   CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
768  * This function (not a handler) is called once and only once per processor.
769  * It signals the processor that the initialization is done and regular messages
770  * can be processed.
772  * On processor zero it is called by _initCharm, on all other processors either
773  * by _initHandler or _triggerHandler (cannot be both).
774  * When fault-tolerance is active, it is called by the fault-tolerance scheme itself.
775  */
776 void _initDone(void)
778   if (CkpvAccess(_initdone)) return;
779   CkpvAccess(_initdone) = true;
780   DEBUGF(("[%d] _initDone.\n", CkMyPe()));
781   if (!CksvAccess(_triggersSent)) _sendTriggers();
782   CkNumberHandler(_triggerHandlerIdx, _discardHandler);
783   CmiNodeBarrier();
784   if(CkMyRank() == 0) {
785     _processBufferedNodeBocInits();
786     quietMode = 0; // re-enable CmiPrintf's if they were disabled
787   }
788   CmiNodeBarrier(); // wait for all nodegroups to be created
789   _processBufferedBocInits();
790   DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
791   CmiNodeBarrier();
792   DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
793   _processBufferedMsgs();
794   CkpvAccess(_charmEpoch)=1;
798  * Converse handler receiving a signal from another processors in the same node.
799  * (On _sendTrigger there is the explanation of why this is necessary)
800  * Simply check if with the NodeGroup processed by another processor we reached
801  * the expected count. Notice that it can only be called before _initDone: after
802  * _initDone, a message destined for this handler will go instead to the _discardHandler.
803  */
804 static void _triggerHandler(envelope *env)
806   if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
807   {
808     DEBUGF(("Calling Init Done from _triggerHandler\n"));
809     _initDone();
810   }
811   if (env!=NULL) CmiFree(env);
814 static inline void _processROMsgMsg(envelope *env)
816   if(!CmiMyRank()) {
817     *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
818   }
821 static inline void _processRODataMsg(envelope *env)
823   //Unpack each readonly:
824   if(!CmiMyRank()) {
825     PUP::fromMem pu((char *)EnvToUsr(env));
826     for(size_t i=0;i<_readonlyTable.size();i++) {
827       _readonlyTable[i]->pupData(pu);
828     }
829   }
830   CmiFree(env);
834  * This is similar to the _initHandler, only that the Groups and Nodegroups are
835  * initialized from disk, so only one single message is expected.
837  * It is unclear how Readonly Messages are treated during restart... (if at all considered)
838  */
839 static void _roRestartHandler(void *msg)
841   CkAssert(CkMyPe()!=0);
842   envelope *env = (envelope *) msg;
843   CkpvAccess(_numInitsRecd)++;
844   _numExpectInitMsgs = env->getCount();
845   _processRODataMsg(env);
846   // in SMP, potentially there us a race condition between rank0 calling
847   // initDone, which sendTriggers, and PE 0 calls bdcastRO which broadcast
848   // readonlys
849   // if this readonly message arrives later, we need to call trigger again
850   // to trigger initDone() on all ranks
851   // we therefore needs to make sure initDone() is exactly 
852   _triggerHandler(NULL);
856  * This handler is used only during initialization. It receives messages from
857  * processor zero regarding Readonly Data (in one single message), Readonly Messages,
858  * Groups, and Nodegroups.
859  * The Readonly Data message also contains the total number of messages expected
860  * during the initialization phase.
861  * For Groups and Nodegroups, only messages with epoch=0 (meaning created from within
862  * a mainchare) are buffered for special creation, the other messages are buffered
863  * together with all the other regular messages by _bufferHandler (and will be flushed
864  * after all the initialization messages have been processed).
865  */
866 static void _initHandler(void *msg, CkCoreState *ck)
868   CkAssert(CkMyPe()!=0);
869   envelope *env = (envelope *) msg;
870   
871   if (ck->watcher!=NULL) {
872     if (!ck->watcher->processMessage(&env,ck)) return;
873   }
874   
875   switch (env->getMsgtype()) {
876     case BocInitMsg:
877       if (env->getGroupEpoch()==0) {
878         CkpvAccess(_numInitsRecd)++;
879         // _processBocInitMsg already handles QD
880         //CpvAccess(_qd)->process();
881         CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
882       } else _bufferHandler(msg);
883       break;
884     case NodeBocInitMsg:
885       if (env->getGroupEpoch()==0) {
886         CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
887         CksvAccess(_numInitNodeMsgs)++;
888         CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
889         CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
890         CpvAccess(_qd)->process();
891       } else _bufferHandler(msg);
892       break;
893     case ROMsgMsg:
894       CkpvAccess(_numInitsRecd)++;
895       CpvAccess(_qd)->process();
896       if(env->isPacked()) CkUnpackMessage(&env);
897       _processROMsgMsg(env);
898       break;
899     case RODataMsg:
900       CkpvAccess(_numInitsRecd)++;
901       CpvAccess(_qd)->process();
902       _numExpectInitMsgs = env->getCount();
903       _processRODataMsg(env);
904       break;
905     default:
906       CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
907   }
908   DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
909   if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
910     _initDone();
911   }
914 #if 0
915 /*****************************************
916  *          no longer needed
917  * ***************************************/
918 extern "C"
919 void _CkExit(void) 
921   CmiAssert(CkMyPe() == 0);
922   // Shuts down Converse handlers for the upper layers on this processor
923   //
924   CkNumberHandler(_charmHandlerIdx,_discardHandler);
925   CkNumberHandler(_bocHandlerIdx, _discardHandler);
926   DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
928   if(CkMyPe()==0) {
929     if(_exitStarted)
930       CsdScheduler(-1);
931     envelope *env = _allocEnv(ReqStatMsg);
932     env->setSrcPe(CkMyPe());
933     CmiSetHandler(env, _exitHandlerIdx);
934                 /*FAULT_EVAC*/
935     CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
936   } else {
937     envelope *env = _allocEnv(ExitMsg);
938     env->setSrcPe(CkMyPe());
939     CmiSetHandler(env, _exitHandlerIdx);
940     CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
941   }
942 #if ! CMK_BIGSIM_THREAD
943   _TRACE_END_EXECUTE();
944   //Wait for stats, which will call ConverseExit when finished:
945   CsdScheduler(-1);
946 #endif
948 #endif
950 #if CMK_SHRINK_EXPAND
951 extern "C"
952 void CkCleanup()
954         // always send to PE 0
955         envelope *env = _allocEnv(StartExitMsg);
956         env->setSrcPe(CkMyPe());
957         CmiSetHandler(env, _exitHandlerIdx);
958         CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
960 #endif
962 CkQ<CkExitFn> _CkExitFnVec;
964 // triger exit on PE 0,
965 // which traverses _CkExitFnVec to call every registered user exit functions.
966 // Every user exit functions should end with CkExit() to continue the chain
967 extern "C"
968 void CkExit(void)
970         /*FAULT_EVAC*/
971   DEBUGF(("[%d] CkExit called \n",CkMyPe()));
972     // always send to PE 0
973   envelope *env = _allocEnv(StartExitMsg);
974   env->setSrcPe(CkMyPe());
975   CmiSetHandler(env, _exitHandlerIdx);
976   CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
978 #if ! CMK_BIGSIM_THREAD
979   _TRACE_END_EXECUTE();
980   //Wait for stats, which will call ConverseExit when finished:
981         if(!CharmLibInterOperate)
982   CsdScheduler(-1);
983 #endif
986 /* This is a routine called in case the application is closing due to a signal.
987    Tear down structures that must be cleaned up even when unclean exit happens.
988    It is called by the machine layer whenever some problem occurs (it is thus up
989    to the machine layer to call this function). */
990 extern "C"
991 void EmergencyExit(void) {
992 #ifndef __BIGSIM__
993   /* Delete _coreState to force any CkMessageWatcher to close down. */
994   if (CkpvAccess(_coreState) != NULL) {
995     delete CkpvAccess(_coreState);
996     CkpvAccess(_coreState) = NULL;
997   }
998 #endif
1001 static void _nullFn(void *, void *)
1003   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
1006 extern void _registerLBDatabase(void);
1007 extern void _registerMetaBalancer(void);
1008 extern void _registerPathHistory(void);
1009 #if CMK_WITH_CONTROLPOINT
1010 extern void _registerControlPoints(void);
1011 #endif
1012 extern void _registerTraceControlPoints();
1013 extern void _registerExternalModules(char **argv);
1014 extern void _ckModuleInit(void);
1015 extern void _loadbalancerInit();
1016 extern void _metabalancerInit();
1017 #if CMK_SMP && CMK_TASKQUEUE
1018 extern void _taskqInit();
1019 #endif
1020 extern void _initChareTables();
1021 #if CMK_MEM_CHECKPOINT
1022 extern void init_memcheckpt(char **argv);
1023 #endif
1024 extern "C" void initCharmProjections();
1025 extern "C" void CmiInitCPUTopology(char **argv);
1026 extern "C" void CmiInitCPUAffinity(char **argv);
1027 extern "C" void CmiInitMemAffinity(char **argv);
1028 extern "C" void CmiInitPxshm(char **argv);
1030 //extern "C" void CldCallback();
1032 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
1034   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
1035   else _initCallTable.initProcCalls.enq(fn);
1038 void InitCallTable::enumerateInitCalls()
1040   int i;
1041 #ifdef __BIGSIM__
1042   if(BgNodeRank()==0)        // called only once on an emulating node
1043 #else
1044   if(CkMyRank()==0) 
1045 #endif
1046   {
1047     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
1048   }
1049   // initproc may depend on initnode calls.
1050   CmiNodeAllBarrier();
1051   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
1054 CpvCExtern(int, cpdSuspendStartup);
1055 extern "C" void CpdFreeze(void);
1057 extern int _dummy_dq;
1059 extern "C" void initQd(char **argv)
1061         CpvInitialize(QdState*, _qd);
1062         CpvAccess(_qd) = new QdState();
1063         if (CmiMyRank() == 0) {
1064 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
1065         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
1066 #endif
1067         }
1068         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
1069         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
1070         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
1071           if (CmiMyPe()==0)
1072             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
1073         }
1076 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1077 void CpdBgInit();
1078 #endif
1079 void CpdBreakPointInit();
1082   This is the main charm setup routine.  It's called
1083   on all processors after Converse initialization.
1084   This routine gets passed to Converse from "main.C".
1085   
1086   The main purpose of this routine is to set up the objects
1087   and Ckpv's used during a regular Charm run.  See the comment
1088   at the top of the file for overall flow.
1090 void _initCharm(int unused_argc, char **argv)
1092         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
1094         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
1096         CkpvInitialize(size_t *, _offsets);
1097         CkpvAccess(_offsets) = new size_t[32];
1098         CkpvInitialize(PtrQ*,_buffQ);
1099         CkpvInitialize(PtrVec*,_bocInitVec);
1100         CkpvInitialize(void*, _currentChare);
1101         CkpvInitialize(int,   _currentChareType);
1102         CkpvInitialize(CkGroupID, _currentGroup);
1103         CkpvInitialize(void *, _currentNodeGroupObj);
1104         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
1105         CkpvInitialize(GroupTable*, _groupTable);
1106         CkpvInitialize(GroupIDTable*, _groupIDTable);
1107         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
1108         CkpvInitialize(bool, _destroyingNodeGroup);
1109         CkpvAccess(_destroyingNodeGroup) = false;
1110         CkpvInitialize(UInt, _numGroups);
1111         CkpvInitialize(int, _numInitsRecd);
1112         CkpvInitialize(bool, _initdone);
1113         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
1114         CkpvInitialize(MsgPool*, _msgPool);
1115         CkpvInitialize(CkCoreState *, _coreState);
1116         /*
1117                 Added for evacuation-sayantan
1118         */
1119 #ifndef __BIGSIM__
1120         CpvInitialize(char *,_validProcessors);
1121 #endif
1122         CkpvInitialize(char ,startedEvac);
1123         CpvInitialize(int,serializer);
1125         _initChareTables();            // for checkpointable plain chares
1127         CksvInitialize(UInt, _numNodeGroups);
1128         CksvInitialize(GroupTable*, _nodeGroupTable);
1129         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
1130         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
1131         CksvInitialize(CmiNodeLock, _nodeLock);
1132         CksvInitialize(PtrVec*,_nodeBocInitVec);
1133         CksvInitialize(UInt,_numInitNodeMsgs);
1134         CkpvInitialize(int,_charmEpoch);
1135         CkpvAccess(_charmEpoch)=0;
1136         CksvInitialize(bool, _triggersSent);
1137         CksvAccess(_triggersSent) = false;
1139         CkpvInitialize(_CkOutStream*, _ckout);
1140         CkpvInitialize(_CkErrStream*, _ckerr);
1141         CkpvInitialize(Stats*, _myStats);
1143         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
1144         CkpvAccess(_groupTable) = new GroupTable;
1145         CkpvAccess(_groupTable)->init();
1146         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
1147         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
1148         CkpvAccess(_buffQ) = new PtrQ();
1149         CkpvAccess(_bocInitVec) = new PtrVec();
1151         CkpvAccess(_currentNodeGroupObj) = NULL;
1153         if(CkMyRank()==0)
1154         {
1155                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
1156                 CksvAccess(_numInitNodeMsgs) = 0;
1157                 CksvAccess(_nodeLock) = CmiCreateLock();
1158                 CksvAccess(_nodeGroupTable) = new GroupTable();
1159                 CksvAccess(_nodeGroupTable)->init();
1160                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
1161                 CksvAccess(_nodeBocInitVec) = new PtrVec();
1162         }
1164         CkCallbackInit();
1165         
1166         CmiNodeAllBarrier();
1168 #if ! CMK_BIGSIM_CHARM
1169         initQd(argv);         // bigsim calls it in ConverseCommonInit
1170 #endif
1172         CkpvAccess(_coreState)=new CkCoreState();
1174         CkpvAccess(_numInitsRecd) = 0;
1175         CkpvAccess(_initdone) = false;
1177         CkpvAccess(_ckout) = new _CkOutStream();
1178         CkpvAccess(_ckerr) = new _CkErrStream();
1180         _charmHandlerIdx = CkRegisterHandler(_bufferHandler);
1181         _initHandlerIdx = CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState));
1182         _roRestartHandlerIdx = CkRegisterHandler(_roRestartHandler);
1183         _exitHandlerIdx = CkRegisterHandler(_exitHandler);
1184         //added for interoperabilitY
1185         _libExitHandlerIdx = CkRegisterHandler(_libExitHandler);
1186         _bocHandlerIdx = CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState));
1187 #if CMK_SHRINK_EXPAND
1188         // for shrink expand cleanup
1189         _ROGroupRestartHandlerIdx = CkRegisterHandler(_ROGroupRestartHandler);
1190 #endif
1192 #ifdef __BIGSIM__
1193         if(BgNodeRank()==0) 
1194 #endif
1195         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1197         _triggerHandlerIdx = CkRegisterHandler(_triggerHandler);
1198         _ckModuleInit();
1200         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1202         _futuresModuleInit(); // part of futures implementation is a converse module
1203         _loadbalancerInit();
1204         _metabalancerInit();
1205 #if CMK_SMP && CMK_TASKQUEUE
1206         _taskqInit();
1207 #endif
1208 #if CMK_MEM_CHECKPOINT
1209         init_memcheckpt(argv);
1210 #endif
1212         initCharmProjections();
1213 #if CMK_TRACE_IN_CHARM
1214         // initialize trace module in ck
1215         traceCharmInit(argv);
1216 #endif
1217         
1218     CkpvInitialize(int, envelopeEventID);
1219     CkpvAccess(envelopeEventID) = 0;
1220         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1221         
1222         /**
1223           The rank-0 processor of each node calls the 
1224           translator-generated "_register" routines. 
1225           
1226           _register routines call the charm.h "CkRegister*" routines,
1227           which record function pointers and class information for
1228           all Charm entities, like Chares, Arrays, and readonlies.
1229           
1230           There's one _register routine generated for each
1231           .ci file.  _register routines *must* be called in the 
1232           same order on every node, and *must not* be called by 
1233           multiple threads simultaniously.
1234         */
1235 #ifdef __BIGSIM__
1236         if(BgNodeRank()==0) 
1237 #else
1238         if(CkMyRank()==0)
1239 #endif
1240         {
1241                 SDAG::registerPUPables();
1242                 CmiArgGroup("Charm++",NULL);
1243                 _parseCommandLineOpts(argv);
1244                 _registerInit();
1245                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1246                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1247                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1248                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1249                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1250                 CkRegisterChareInCharm(CkIndex_Group::__idx);
1251                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1252                 
1253                 /**
1254                   These _register calls are for the built-in
1255                   Charm .ci files, like arrays and load balancing.
1256                   If you add a .ci file to charm, you'll have to 
1257                   add a call to the _register routine here, or make
1258                   your library into a "-module".
1259                 */
1260                 _registerCkFutures();
1261                 _registerCkArray();
1262                 _registerLBDatabase();
1263     _registerMetaBalancer();
1264                 _registerCkCallback();
1265                 _registertempo();
1266                 _registerwaitqd();
1267                 _registerCkCheckpoint();
1268                 _registerCkMulticast();
1269 #if CMK_MEM_CHECKPOINT
1270                 _registerCkMemCheckpoint();
1271 #endif
1273                 /**
1274                   CkRegisterMainModule is generated by the (unique)
1275                   "mainmodule" .ci file.  It will include calls to 
1276                   register all the .ci files.
1277                 */
1278                 CkRegisterMainModule();
1280                 /**
1281                   _registerExternalModules is actually generated by 
1282                   charmc at link time (as "moduleinit<pid>.C").  
1283                   
1284                   This generated routine calls the _register functions
1285                   for the .ci files of libraries linked using "-module".
1286                   This funny initialization is most useful for AMPI/FEM
1287                   programs, which don't have a .ci file and hence have
1288                   no other way to control the _register process.
1289                 */
1290                 _registerExternalModules(argv);
1291                 
1292                 _registerDone();
1293         }
1294         /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1295         if (CkMyRank() == 0) {
1296           CpdBreakPointInit();
1297         }
1298         CmiNodeAllBarrier();
1300         // Execute the initcalls registered in modules
1301         _initCallTable.enumerateInitCalls();
1303 #if CMK_CHARMDEBUG
1304         CpdFinishInitialization();
1305 #endif
1307         //CmiNodeAllBarrier();
1309         CkpvAccess(_myStats) = new Stats();
1310         CkpvAccess(_msgPool) = new MsgPool();
1312         CmiNodeAllBarrier();
1314 #if !(__FAULT__)
1315         CmiBarrier();
1316         CmiBarrier();
1317         CmiBarrier();
1318 #endif
1319 #if CMK_SMP_TRACE_COMMTHREAD
1320         _TRACE_BEGIN_COMPUTATION();     
1321 #else
1322         if (!inCommThread) {
1323           _TRACE_BEGIN_COMPUTATION();
1324         }
1325 #endif
1327 #ifdef ADAPT_SCHED_MEM
1328     if(CkMyRank()==0){
1329         memCriticalEntries = new int[numMemCriticalEntries];
1330         int memcnt=0;
1331         for(int i=0; i<_entryTable.size(); i++){
1332             if(_entryTable[i]->isMemCritical){
1333                 memCriticalEntries[memcnt++] = i;
1334             }
1335         }
1336     }
1337 #endif
1339 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1340     _messageLoggingInit();
1341 #endif
1343 #ifndef __BIGSIM__
1344         /*
1345                 FAULT_EVAC
1346         */
1347         CpvAccess(_validProcessors) = new char[CkNumPes()];
1348         for(int vProc=0;vProc<CkNumPes();vProc++){
1349                 CpvAccess(_validProcessors)[vProc]=1;
1350         }
1351         _ckEvacBcastIdx = CkRegisterHandler(_ckEvacBcast);
1352         _ckAckEvacIdx = CkRegisterHandler(_ckAckEvac);
1353 #endif
1354         CkpvAccess(startedEvac) = 0;
1355         CpvAccess(serializer) = 0;
1357         evacuate = 0;
1358         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1359 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
1360     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1361 #endif
1363         if(_raiseEvac){
1364                 processRaiseEvacFile(_raiseEvacFile);
1365                 /*
1366                 if(CkMyPe() == 2){
1367                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1368                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1369                 }
1370                 if(CkMyPe() == 3){
1371                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1372                 }*/
1373         }       
1374     
1375     if (CkMyRank() == 0) {
1376       TopoManager_init();
1377     }
1378     CmiNodeAllBarrier();
1380     if (!_replaySystem) {
1381         CkFtFn  faultFunc_restart = CkRestartMain;
1382         if (faultFunc == NULL || faultFunc == faultFunc_restart) {         // this is not restart from memory
1383             // these two are blocking calls for non-bigsim
1384 #if ! CMK_BIGSIM_CHARM
1385           CmiInitCPUAffinity(argv);
1386           CmiInitMemAffinity(argv);
1387 #endif
1388         }
1389         CmiInitCPUTopology(argv);
1390 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1391         if (CmiCpuTopologyEnabled()) {
1392             int *pelist;
1393             int num;
1394             CmiGetPesOnPhysicalNode(0, &pelist, &num);
1395 #if !CMK_MULTICORE && !CMK_SMP_NO_COMMTHD
1396             // Count communication threads, if present
1397             // XXX: Assuming uniformity of node size here
1398             num += num/CmiMyNodeSize();
1399 #endif
1400             if (!_Cmi_forceSpinOnIdle && num > CmiNumCores())
1401             {
1402               if (CmiMyPe() == 0)
1403                 CmiPrintf("\nCharm++> Warning: the number of SMP threads (%d) is greater than the number of physical cores (%d), so threads will sleep while idling. Use +CmiSpinOnIdle or +CmiSleepOnIdle to control this directly.\n\n", num, CmiNumCores());
1404               CmiLock(CksvAccess(_nodeLock));
1405               if (! _Cmi_sleepOnIdle) _Cmi_sleepOnIdle = 1;
1406               CmiUnlock(CksvAccess(_nodeLock));
1407             }
1408         }
1409 #endif
1410     }
1412 #if CMK_CUDA
1413     if (CmiMyRank() == 0) {
1414       initHybridAPI();
1415     }
1416 #endif
1418     if(CmiMyPe() == 0) {
1419         char *topoFilename;
1420         if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name")) 
1421         {
1422             std::stringstream sstm;
1423             sstm << topoFilename << "." << CmiMyPartition();
1424             std::string result = sstm.str();
1425             FILE *fp;
1426             fp = fopen(result.c_str(), "w");
1427             if (fp == NULL) {
1428               CkPrintf("Error opening %s file, writing to stdout\n", topoFilename);
1429               fp = stdout;
1430             }
1431             TopoManager_printAllocation(fp);
1432             fclose(fp);
1433         }
1434     }
1436 #if CMK_USE_PXSHM && ( CMK_CRAYXE || CMK_CRAYXC ) && CMK_SMP
1437       // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized
1438       // again after cpuaffinity is done
1439     if (CkMyRank() == 0) {
1440       CmiInitPxshm(argv);
1441     }
1442     CmiNodeAllBarrier();
1443 #endif
1445     //CldCallback();
1446 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1447       // Register the BG handler for CCS. Notice that this is put into a variable shared by
1448       // the whole real processor. This because converse needs to find it. We check that all
1449       // virtual processors register the same index for this handler.
1450     CpdBgInit();
1451 #endif
1453         if (faultFunc) {
1454 #if CMK_WITH_STATS
1455                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1456 #endif
1457                 if (!inCommThread) {
1458                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1459                   msg->argc = CmiGetArgc(argv);
1460                   msg->argv = argv;
1461                   faultFunc(_restartDir, msg);
1462                   CkFreeMsg(msg);
1463                 }
1464         }else if(CkMyPe()==0){
1465 #if CMK_WITH_STATS
1466                 _allStats = new Stats*[CkNumPes()];
1467 #endif
1468                 size_t i, nMains=_mainTable.size();
1470                 // Check CkArgMsg and warn if it contains any args starting with '+'.
1471                 // These args may be args intended for Charm++ but because of the specific
1472                 // build, were not parsed by the RTS.
1473                 int count = 0;
1474                 int argc = CmiGetArgc(argv);
1475                 for (int i = 1; i < argc; i++) {
1476                         // The +vp option for TCharm is a special case that needs to be checked
1477                         // separately, because the number passed does not need a space after
1478                         // the vp, and the option can be specified with a '+' or a '-'.
1479                         if (strncmp(argv[i],"+vp",3) == 0) {
1480                                 if (_optSet.count("+vp") == 0) {
1481                                         count++;
1482                                         CmiPrintf("WARNING: %s is a TCharm command line argument, but you have not compiled with TCharm\n", argv[i]);
1483                                 }
1484                         } else if (strncmp(argv[i],"-vp",3) == 0) {
1485                                 CmiPrintf("WARNING: %s is no longer valid because -vp has been deprecated. Please use +vp.\n", argv[i]);
1486                         } else if (argv[i][0] == '+' && _optSet.count(argv[i]) == 0) {
1487                                 count++;
1488                                 CmiPrintf("WARNING: %s is a command line argument beginning with a '+' but was not parsed by the RTS.\n", argv[i]);
1489                         } else if (argv[i][0] == '+' && _optSet.count(argv[i]) != 0) {
1490                                 fprintf(stderr,"%s is used more than once. Please remove duplicate arguments.\n", argv[i]);
1491                                 CmiAbort("Bad command-line argument\n");
1492                         }
1493                 }
1494                 if (count) {
1495                         CmiPrintf("If any of the above arguments were intended for the RTS you may need to recompile Charm++ with different options.\n");
1496                 }
1498                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1499                 {
1500                         size_t size = _chareTable[_mainTable[i]->chareIdx]->size;
1501                         void *obj = malloc(size);
1502                         _MEMCHECK(obj);
1503                         _mainTable[i]->setObj(obj);
1504                         CkpvAccess(_currentChare) = obj;
1505                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1506                         CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1507                         msg->argc = CmiGetArgc(argv);
1508                         msg->argv = argv;
1509       quietMode = 0;  // allow printing any mainchare user messages
1510                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1511       if (quietModeRequested) quietMode = 1;
1512 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1513             CpvAccess(_currentObj) = (Chare *)obj;
1514 #endif
1515                 }
1516                 _mainDone = true;
1518                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1519                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1524                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1525                 {
1526                         void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1527                         if(roMsg==0)
1528                                 continue;
1529                         //Pack the message and send it to all other processors
1530                         envelope *env = UsrToEnv(roMsg);
1531                         env->setSrcPe(CkMyPe());
1532                         env->setMsgtype(ROMsgMsg);
1533                         env->setRoIdx(i);
1534                         CmiSetHandler(env, _initHandlerIdx);
1535                         CkPackMessage(&env);
1536                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1537                         CpvAccess(_qd)->create(CkNumPes()-1);
1539                         //For processor 0, unpack and re-set the global
1540                         CkUnpackMessage(&env);
1541                         _processROMsgMsg(env);
1542                         _numInitMsgs++;
1543                 }
1545                 //Determine the size of the RODataMessage
1546                 PUP::sizer ps;
1547                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1549                 //Allocate and fill out the RODataMessage
1550                 envelope *env = _allocEnv(RODataMsg, ps.size());
1551                 PUP::toMem pp((char *)EnvToUsr(env));
1552                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1554                 env->setCount(++_numInitMsgs);
1555                 env->setSrcPe(CkMyPe());
1556                 CmiSetHandler(env, _initHandlerIdx);
1557                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1558                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1559                 CpvAccess(_qd)->create(CkNumPes()-1);
1560                 _initDone();
1561         }
1563         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1564         // when I am a communication thread, I don't participate initDone.
1565         if (inCommThread) {
1566                 CkNumberHandlerEx(_bocHandlerIdx, _processHandler, CkpvAccess(_coreState));
1567                 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
1568                 _processBufferedMsgs();
1569         }
1571 #if CMK_CHARMDEBUG
1572         // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1573        if (CpvAccess(cpdSuspendStartup))
1574        { 
1575           //CmiPrintf("In Parallel Debugging mode .....\n");
1576           CpdFreeze();
1577        }
1578 #endif
1581 #if __FAULT__
1582         if(killFlag){                                                  
1583                 readKillFile();                                        
1584         }
1585 #endif
1589 // this is needed because on o2k, f90 programs have to have main in
1590 // fortran90.
1591 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1593   int i;
1594   char **argv = new char*[*argc+2];
1596   for(i=0;i <= *argc;i++) {
1597     if (length[i] < 100) {
1598       _argv[i][length[i]]='\0';
1599       argv[i] = &(_argv[i][0]);
1600     } else {
1601       argv[i][0] = '\0';
1602     }
1603   }
1604   argv[*argc+1]=0;
1606   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1609 // user callable function to register an exit function, this function
1610 // will perform task of collecting of info from all pes to pe0, and call
1611 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1612 // see trace-summary for an example.
1613 void registerExitFn(CkExitFn fn)
1615 #if CMK_SHRINK_EXPAND
1616   CkAbort("registerExitFn is called when shrink-expand is enabled!");
1617 #else
1618   _CkExitFnVec.enq(fn);
1619 #endif
1622 /*@}*/