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