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