Feature #1730: set std::set_terminate for charm++ applications
[charm.git] / src / ck-core / init.C
blob7421d65d3185a1e7596a2aff0f71cea446142b00
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 CpvExtern(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 CMI_EXTERNC_VARIABLE int quietMode;
233 CMI_EXTERNC_VARIABLE 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 #if CMK_SMP
997 extern void LBTopoInit();
998 #endif
999 extern void _initChareTables();
1000 #if CMK_MEM_CHECKPOINT
1001 extern void init_memcheckpt(char **argv);
1002 #endif
1003 extern "C" void initCharmProjections();
1004 extern "C" void CmiInitCPUTopology(char **argv);
1005 extern "C" void CmiCheckAffinity();
1006 extern "C" void CmiInitMemAffinity(char **argv);
1007 extern "C" void CmiInitPxshm(char **argv);
1009 //extern "C" void CldCallback();
1011 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
1013   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
1014   else _initCallTable.initProcCalls.enq(fn);
1017 void InitCallTable::enumerateInitCalls()
1019   int i;
1020 #ifdef __BIGSIM__
1021   if(BgNodeRank()==0)        // called only once on an emulating node
1022 #else
1023   if(CkMyRank()==0) 
1024 #endif
1025   {
1026     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
1027   }
1028   // initproc may depend on initnode calls.
1029   CmiNodeAllBarrier();
1030   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
1033 CpvCExtern(int, cpdSuspendStartup);
1034 extern "C" void CpdFreeze(void);
1036 extern int _dummy_dq;
1038 extern "C" void initQd(char **argv)
1040         CpvInitialize(QdState*, _qd);
1041         CpvAccess(_qd) = new QdState();
1042         if (CmiMyRank() == 0) {
1043 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
1044         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
1045 #endif
1046         }
1047         CmiAssignOnce(&_qdHandlerIdx, CmiRegisterHandler((CmiHandler)_qdHandler));
1048         CmiAssignOnce(&_qdCommHandlerIdx, CmiRegisterHandler((CmiHandler)_qdCommHandler));
1049         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
1050           if (CmiMyPe()==0)
1051             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
1052         }
1055 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1056 void CpdBgInit();
1057 #endif
1058 void CpdBreakPointInit();
1061   This is the main charm setup routine.  It's called
1062   on all processors after Converse initialization.
1063   This routine gets passed to Converse from "main.C".
1064   
1065   The main purpose of this routine is to set up the objects
1066   and Ckpv's used during a regular Charm run.  See the comment
1067   at the top of the file for overall flow.
1069 void _initCharm(int unused_argc, char **argv)
1071         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
1073         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
1074         std::set_terminate([](){ CkAbort("Unhandled C++ exception in user code.\n");});
1076         CkpvInitialize(size_t *, _offsets);
1077         CkpvAccess(_offsets) = new size_t[32];
1078         CkpvInitialize(PtrQ*,_buffQ);
1079         CkpvInitialize(PtrVec*,_bocInitVec);
1080         CkpvInitialize(void*, _currentChare);
1081         CkpvInitialize(int,   _currentChareType);
1082         CkpvInitialize(CkGroupID, _currentGroup);
1083         CkpvInitialize(void *, _currentNodeGroupObj);
1084         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
1085         CkpvInitialize(GroupTable*, _groupTable);
1086         CkpvInitialize(GroupIDTable*, _groupIDTable);
1087         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
1088         CkpvInitialize(bool, _destroyingNodeGroup);
1089         CkpvAccess(_destroyingNodeGroup) = false;
1090         CkpvInitialize(UInt, _numGroups);
1091         CkpvInitialize(int, _numInitsRecd);
1092         CkpvInitialize(bool, _initdone);
1093         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
1094         CkpvInitialize(MsgPool*, _msgPool);
1095         CkpvInitialize(CkCoreState *, _coreState);
1096         /*
1097                 Added for evacuation-sayantan
1098         */
1099 #ifndef __BIGSIM__
1100         CpvInitialize(char *,_validProcessors);
1101 #endif
1102         CkpvInitialize(char ,startedEvac);
1103         CpvInitialize(int,serializer);
1105         _initChareTables();            // for checkpointable plain chares
1107         CksvInitialize(UInt, _numNodeGroups);
1108         CksvInitialize(GroupTable*, _nodeGroupTable);
1109         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
1110         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
1111         CksvInitialize(CmiNodeLock, _nodeLock);
1112         CksvInitialize(PtrVec*,_nodeBocInitVec);
1113         CksvInitialize(UInt,_numInitNodeMsgs);
1114         CkpvInitialize(int,_charmEpoch);
1115         CkpvAccess(_charmEpoch)=0;
1116         CksvInitialize(bool, _triggersSent);
1117         CksvAccess(_triggersSent) = false;
1119         CkpvInitialize(_CkOutStream*, _ckout);
1120         CkpvInitialize(_CkErrStream*, _ckerr);
1121         CkpvInitialize(Stats*, _myStats);
1123         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
1124         CkpvAccess(_groupTable) = new GroupTable;
1125         CkpvAccess(_groupTable)->init();
1126         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
1127         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
1128         CkpvAccess(_buffQ) = new PtrQ();
1129         CkpvAccess(_bocInitVec) = new PtrVec();
1131         CkpvAccess(_currentNodeGroupObj) = NULL;
1133         if(CkMyRank()==0)
1134         {
1135                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
1136                 CksvAccess(_numInitNodeMsgs) = 0;
1137                 CksvAccess(_nodeLock) = CmiCreateLock();
1138                 CksvAccess(_nodeGroupTable) = new GroupTable();
1139                 CksvAccess(_nodeGroupTable)->init();
1140                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
1141                 CksvAccess(_nodeBocInitVec) = new PtrVec();
1142         }
1144         CkCallbackInit();
1145         
1146         CmiNodeAllBarrier();
1148 #if ! CMK_BIGSIM_CHARM
1149         initQd(argv);         // bigsim calls it in ConverseCommonInit
1150 #endif
1152         CkpvAccess(_coreState)=new CkCoreState();
1154         CkpvAccess(_numInitsRecd) = 0;
1155         CkpvAccess(_initdone) = false;
1157         CkpvAccess(_ckout) = new _CkOutStream();
1158         CkpvAccess(_ckerr) = new _CkErrStream();
1160         CmiAssignOnce(&_charmHandlerIdx, CkRegisterHandler(_bufferHandler));
1161         CmiAssignOnce(&_initHandlerIdx, CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState)));
1162         CmiAssignOnce(&_roRestartHandlerIdx, CkRegisterHandler(_roRestartHandler));
1163         CmiAssignOnce(&_exitHandlerIdx, CkRegisterHandler(_exitHandler));
1164         //added for interoperabilitY
1165         CmiAssignOnce(&_libExitHandlerIdx, CkRegisterHandler(_libExitHandler));
1166         CmiAssignOnce(&_bocHandlerIdx, CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState)));
1167 #if CMK_SHRINK_EXPAND
1168         // for shrink expand cleanup
1169         CmiAssignOnce(&_ROGroupRestartHandlerIdx, CkRegisterHandler(_ROGroupRestartHandler));
1170 #endif
1172 #ifdef __BIGSIM__
1173         if(BgNodeRank()==0) 
1174 #endif
1175         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1177         CmiAssignOnce(&_triggerHandlerIdx, CkRegisterHandler(_triggerHandler));
1178         _ckModuleInit();
1180         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1182         _futuresModuleInit(); // part of futures implementation is a converse module
1183         _loadbalancerInit();
1184         _metabalancerInit();
1186 #if CMK_SMP
1187         if (CmiMyRank() == 0) {
1188                 LBTopoInit();
1189         }
1190 #endif
1191 #if CMK_MEM_CHECKPOINT
1192         init_memcheckpt(argv);
1193 #endif
1195         initCharmProjections();
1196 #if CMK_TRACE_IN_CHARM
1197         // initialize trace module in ck
1198         traceCharmInit(argv);
1199 #endif
1200         
1201     CkpvInitialize(int, envelopeEventID);
1202     CkpvAccess(envelopeEventID) = 0;
1203         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1204         
1205         /**
1206           The rank-0 processor of each node calls the 
1207           translator-generated "_register" routines. 
1208           
1209           _register routines call the charm.h "CkRegister*" routines,
1210           which record function pointers and class information for
1211           all Charm entities, like Chares, Arrays, and readonlies.
1212           
1213           There's one _register routine generated for each
1214           .ci file.  _register routines *must* be called in the 
1215           same order on every node, and *must not* be called by 
1216           multiple threads simultaniously.
1217         */
1218 #ifdef __BIGSIM__
1219         if(BgNodeRank()==0) 
1220 #else
1221         if(CkMyRank()==0)
1222 #endif
1223         {
1224                 SDAG::registerPUPables();
1225                 CmiArgGroup("Charm++",NULL);
1226                 _parseCommandLineOpts(argv);
1227                 _registerInit();
1228                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1229                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1230                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1231                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1232                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1233                 CkRegisterChareInCharm(CkIndex_Group::__idx);
1234                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1235                 
1236                 /**
1237                   These _register calls are for the built-in
1238                   Charm .ci files, like arrays and load balancing.
1239                   If you add a .ci file to charm, you'll have to 
1240                   add a call to the _register routine here, or make
1241                   your library into a "-module".
1242                 */
1243                 _registerCkFutures();
1244                 _registerCkArray();
1245                 _registerLBDatabase();
1246     _registerMetaBalancer();
1247                 _registerCkCallback();
1248                 _registerwaitqd();
1249                 _registerCkCheckpoint();
1250                 _registerCkMulticast();
1251 #if CMK_MEM_CHECKPOINT
1252                 _registerCkMemCheckpoint();
1253 #endif
1255                 /**
1256                   CkRegisterMainModule is generated by the (unique)
1257                   "mainmodule" .ci file.  It will include calls to 
1258                   register all the .ci files.
1259                 */
1260                 CkRegisterMainModule();
1262                 /**
1263                   _registerExternalModules is actually generated by 
1264                   charmc at link time (as "moduleinit<pid>.C").  
1265                   
1266                   This generated routine calls the _register functions
1267                   for the .ci files of libraries linked using "-module".
1268                   This funny initialization is most useful for AMPI/FEM
1269                   programs, which don't have a .ci file and hence have
1270                   no other way to control the _register process.
1271                 */
1272                 _registerExternalModules(argv);
1273         }
1275         /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1276         if (CkMyRank() == 0) {
1277           CpdBreakPointInit();
1278         }
1279         CmiNodeAllBarrier();
1281         // Execute the initcalls registered in modules
1282         _initCallTable.enumerateInitCalls();
1284 #if CMK_CHARMDEBUG
1285         CpdFinishInitialization();
1286 #endif
1287         if (CkMyRank() == 0)
1288           _registerDone();
1289         CmiNodeAllBarrier();
1291         CkpvAccess(_myStats) = new Stats();
1292         CkpvAccess(_msgPool) = new MsgPool();
1294         CmiNodeAllBarrier();
1296 #if !(__FAULT__)
1297         CmiBarrier();
1298         CmiBarrier();
1299         CmiBarrier();
1300 #endif
1301 #if CMK_SMP_TRACE_COMMTHREAD
1302         _TRACE_BEGIN_COMPUTATION();     
1303 #else
1304         if (!inCommThread) {
1305           _TRACE_BEGIN_COMPUTATION();
1306         }
1307 #endif
1309 #ifdef ADAPT_SCHED_MEM
1310     if(CkMyRank()==0){
1311         memCriticalEntries = new int[numMemCriticalEntries];
1312         int memcnt=0;
1313         for(int i=0; i<_entryTable.size(); i++){
1314             if(_entryTable[i]->isMemCritical){
1315                 memCriticalEntries[memcnt++] = i;
1316             }
1317         }
1318     }
1319 #endif
1321 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1322     _messageLoggingInit();
1323 #endif
1325 #ifndef __BIGSIM__
1326         /*
1327                 FAULT_EVAC
1328         */
1329         CpvAccess(_validProcessors) = new char[CkNumPes()];
1330         for(int vProc=0;vProc<CkNumPes();vProc++){
1331                 CpvAccess(_validProcessors)[vProc]=1;
1332         }
1333         CmiAssignOnce(&_ckEvacBcastIdx, CkRegisterHandler(_ckEvacBcast));
1334         CmiAssignOnce(&_ckAckEvacIdx, CkRegisterHandler(_ckAckEvac));
1335 #endif
1336         CkpvAccess(startedEvac) = 0;
1337         CpvAccess(serializer) = 0;
1339         evacuate = 0;
1340         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1341 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
1342     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1343 #endif
1345         if(_raiseEvac){
1346                 processRaiseEvacFile(_raiseEvacFile);
1347                 /*
1348                 if(CkMyPe() == 2){
1349                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1350                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1351                 }
1352                 if(CkMyPe() == 3){
1353                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1354                 }*/
1355         }       
1356     
1357     if (CkMyRank() == 0) {
1358       TopoManager_init();
1359     }
1360     CmiNodeAllBarrier();
1362     if (!_replaySystem) {
1363         CkFtFn  faultFunc_restart = CkRestartMain;
1364         if (faultFunc == NULL || faultFunc == faultFunc_restart) {         // this is not restart from memory
1365             // these two are blocking calls for non-bigsim
1366 #if ! CMK_BIGSIM_CHARM
1367           CmiInitCPUAffinity(argv);
1368           CmiInitMemAffinity(argv);
1369 #endif
1370         }
1371         CmiInitCPUTopology(argv);
1372         if (CkMyRank() == 0) {
1373           TopoManager_reset(); // initialize TopoManager singleton
1374 #if !CMK_BIGSIM_CHARM
1375           _topoTree = ST_RecursivePartition_getTreeInfo(0);
1376 #endif
1377         }
1378         CmiNodeAllBarrier(); // threads wait until _topoTree has been generated
1379 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1380         if (CmiCpuTopologyEnabled()) {
1381             int *pelist;
1382             int num;
1383             CmiGetPesOnPhysicalNode(0, &pelist, &num);
1384 #if !CMK_MULTICORE && !CMK_SMP_NO_COMMTHD
1385             // Count communication threads, if present
1386             // XXX: Assuming uniformity of node size here
1387             num += num/CmiMyNodeSize();
1388 #endif
1389             if (!_Cmi_forceSpinOnIdle && num > CmiNumCores())
1390             {
1391               if (CmiMyPe() == 0)
1392                 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());
1393               CmiLock(CksvAccess(_nodeLock));
1394               if (! _Cmi_sleepOnIdle) _Cmi_sleepOnIdle = 1;
1395               CmiUnlock(CksvAccess(_nodeLock));
1396             }
1397         }
1398 #endif
1399     }
1401 #if CMK_CUDA
1402     if (CmiMyRank() == 0) {
1403       initHybridAPI();
1404     }
1405 #endif
1407     if(CmiMyPe() == 0) {
1408         char *topoFilename;
1409         if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name")) 
1410         {
1411             std::stringstream sstm;
1412             sstm << topoFilename << "." << CmiMyPartition();
1413             std::string result = sstm.str();
1414             FILE *fp;
1415             fp = fopen(result.c_str(), "w");
1416             if (fp == NULL) {
1417               CkPrintf("Error opening %s file, writing to stdout\n", topoFilename);
1418               fp = stdout;
1419             }
1420             TopoManager_printAllocation(fp);
1421             fclose(fp);
1422         }
1423     }
1425 #if CMK_USE_PXSHM && ( CMK_CRAYXE || CMK_CRAYXC ) && CMK_SMP
1426       // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized
1427       // again after cpuaffinity is done
1428     if (CkMyRank() == 0) {
1429       CmiInitPxshm(argv);
1430     }
1431     CmiNodeAllBarrier();
1432 #endif
1434     //CldCallback();
1435 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1436       // Register the BG handler for CCS. Notice that this is put into a variable shared by
1437       // the whole real processor. This because converse needs to find it. We check that all
1438       // virtual processors register the same index for this handler.
1439     CpdBgInit();
1440 #endif
1442         if (faultFunc) {
1443 #if CMK_WITH_STATS
1444                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1445 #endif
1446                 if (!inCommThread) {
1447                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1448                   msg->argc = CmiGetArgc(argv);
1449                   msg->argv = argv;
1450                   faultFunc(_restartDir, msg);
1451                   CkFreeMsg(msg);
1452                 }
1453         }else if(CkMyPe()==0){
1454 #if CMK_WITH_STATS
1455                 _allStats = new Stats*[CkNumPes()];
1456 #endif
1457                 size_t i, nMains=_mainTable.size();
1459                 // Check CkArgMsg and warn if it contains any args starting with '+'.
1460                 // These args may be args intended for Charm++ but because of the specific
1461                 // build, were not parsed by the RTS.
1462                 int count = 0;
1463                 int argc = CmiGetArgc(argv);
1464                 for (int i = 1; i < argc; i++) {
1465                         // The +vp option for TCharm is a special case that needs to be checked
1466                         // separately, because the number passed does not need a space after
1467                         // the vp, and the option can be specified with a '+' or a '-'.
1468                         if (strncmp(argv[i],"+vp",3) == 0) {
1469                                 if (_optSet.count("+vp") == 0) {
1470                                         count++;
1471                                         CmiPrintf("WARNING: %s is a TCharm command line argument, but you have not compiled with TCharm\n", argv[i]);
1472                                 }
1473                         } else if (strncmp(argv[i],"-vp",3) == 0) {
1474                                 CmiPrintf("WARNING: %s is no longer valid because -vp has been deprecated. Please use +vp.\n", argv[i]);
1475                         } else if (argv[i][0] == '+' && _optSet.count(argv[i]) == 0) {
1476                                 count++;
1477                                 CmiPrintf("WARNING: %s is a command line argument beginning with a '+' but was not parsed by the RTS.\n", argv[i]);
1478                         } else if (argv[i][0] == '+' && _optSet.count(argv[i]) != 0) {
1479                                 fprintf(stderr,"%s is used more than once. Please remove duplicate arguments.\n", argv[i]);
1480                                 CmiAbort("Bad command-line argument\n");
1481                         }
1482                 }
1483                 if (count) {
1484                         CmiPrintf("If any of the above arguments were intended for the RTS you may need to recompile Charm++ with different options.\n");
1485                 }
1487                 CmiCheckAffinity(); // check for thread oversubscription
1489                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1490                 {
1491                         size_t size = _chareTable[_mainTable[i]->chareIdx]->size;
1492                         void *obj = malloc(size);
1493                         _MEMCHECK(obj);
1494                         _mainTable[i]->setObj(obj);
1495                         CkpvAccess(_currentChare) = obj;
1496                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1497                         CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1498                         msg->argc = CmiGetArgc(argv);
1499                         msg->argv = argv;
1500       quietMode = 0;  // allow printing any mainchare user messages
1501                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1502       if (quietModeRequested) quietMode = 1;
1503 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1504             CpvAccess(_currentObj) = (Chare *)obj;
1505 #endif
1506                 }
1507                 _mainDone = true;
1509                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1510                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1515                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1516                 {
1517                         void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1518                         if(roMsg==0)
1519                                 continue;
1520                         //Pack the message and send it to all other processors
1521                         envelope *env = UsrToEnv(roMsg);
1522                         env->setSrcPe(CkMyPe());
1523                         env->setMsgtype(ROMsgMsg);
1524                         env->setRoIdx(i);
1525                         CmiSetHandler(env, _initHandlerIdx);
1526                         CkPackMessage(&env);
1527                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1528                         CpvAccess(_qd)->create(CkNumPes()-1);
1530                         //For processor 0, unpack and re-set the global
1531                         CkUnpackMessage(&env);
1532                         _processROMsgMsg(env);
1533                         _numInitMsgs++;
1534                 }
1536                 //Determine the size of the RODataMessage
1537                 PUP::sizer ps;
1538                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1540                 //Allocate and fill out the RODataMessage
1541                 envelope *env = _allocEnv(RODataMsg, ps.size());
1542                 PUP::toMem pp((char *)EnvToUsr(env));
1543                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1545                 env->setCount(++_numInitMsgs);
1546                 env->setSrcPe(CkMyPe());
1547                 CmiSetHandler(env, _initHandlerIdx);
1548                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1549                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1550                 CpvAccess(_qd)->create(CkNumPes()-1);
1551                 _initDone();
1552         } else {
1553                 // check for thread oversubscription
1554                 CmiCheckAffinity();
1555                 // NOTE: this assumes commthreads will not block from this point on
1556         }
1558         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1559         // when I am a communication thread, I don't participate initDone.
1560         if (inCommThread) {
1561                 CkNumberHandlerEx(_bocHandlerIdx, _processHandler, CkpvAccess(_coreState));
1562                 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
1563                 _processBufferedMsgs();
1564         }
1566 #if CMK_CHARMDEBUG
1567         // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1568        if (CpvAccess(cpdSuspendStartup))
1569        { 
1570           //CmiPrintf("In Parallel Debugging mode .....\n");
1571           CpdFreeze();
1572        }
1573 #endif
1576 #if __FAULT__
1577         if(killFlag){                                                  
1578                 readKillFile();                                        
1579         }
1580 #endif
1584 // this is needed because on o2k, f90 programs have to have main in
1585 // fortran90.
1586 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1588   int i;
1589   char **argv = new char*[*argc+2];
1591   for(i=0;i <= *argc;i++) {
1592     if (length[i] < 100) {
1593       _argv[i][length[i]]='\0';
1594       argv[i] = &(_argv[i][0]);
1595     } else {
1596       argv[i][0] = '\0';
1597     }
1598   }
1599   argv[*argc+1]=0;
1601   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1604 // user callable function to register an exit function, this function
1605 // will perform task of collecting of info from all pes to pe0, and call
1606 // CkContinueExit() on pe0 again to recursively traverse the registered exitFn.
1607 // see trace-summary for an example.
1608 void registerExitFn(CkExitFn fn)
1610 #if CMK_SHRINK_EXPAND
1611   CkAbort("registerExitFn is called when shrink-expand is enabled!");
1612 #else
1613   _CkExitFnVec.enq(fn);
1614 #endif
1617 /*@}*/