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
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.
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:
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
61 This process should not have race conditions, but it can
66 #include "ckcheckpoint.h"
70 #include "CkCheckpoint.decl.h"
71 #include "ckmulticast.h"
74 #include "spanningTree.h"
76 #include "GreedyRefineLB.h"
80 #include "hapi_impl.h"
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;
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).
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.
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.
115 CksvDeclare(UInt,_numInitNodeMsgs);
117 int _charmHandlerIdx;
119 int _roRestartHandlerIdx;
122 int _qdCommHandlerIdx;
123 int _triggerHandlerIdx;
124 bool _mainDone = false;
125 CksvDeclare(bool, _triggersSent);
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;
177 CpvExtern(char *, _validProcessors);
178 CkpvDeclare(char ,startedEvac);
184 static Stats** _allStats = 0;
186 static bool _exitStarted = false;
187 static int _exitcode;
189 static InitCallTable _initCallTable;
192 #define _STATS_ON(x) (x) = 1
194 #define _STATS_ON(x) \
195 if (CkMyPe()==0) CmiPrintf("stats unavailable in optimized version. ignoring...\n");
199 typedef void (*CkFtFn)(const char *, CkArgMsg *);
200 static CkFtFn faultFunc = NULL;
201 static char* _restartDir;
203 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
205 int chkptPeriod=1000;
206 bool fastRecovery = false;
207 int parallelRecovery = 1;
208 extern int BUFFER_TIME; //time spent waiting for buffered messages
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
217 #if CMK_MESSAGE_LOGGING
218 // flag for disk checkpoint
219 extern bool diskCkptFlag;
222 int _defaultObjectQ = 0; // for obejct queue
223 bool _ringexit = 0; // for charm exit
225 extern int _messageBufferingThreshold;
228 static bool _raiseEvac=0; // whether or not to trigger the processor shutdowns
229 static char *_raiseEvacFile;
230 void processRaiseEvacFile(char *raiseEvacFile);
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.
252 static inline void _parseCommandLineOpts(char **argv)
254 if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
256 if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
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"))
272 #if CMK_OBJECT_QUEUE_AVAILABLE
275 CmiPrintf("Charm++> Create object queue for every Charm object.\n");
277 CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
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";
287 _shrinkexpand_basedir = "/dev/shm";
291 if(CmiGetArgString(argv,"+restart",&_restartDir))
292 faultFunc = CkRestartMain;
294 if (CmiGetArgIntDesc(argv,"+restartaftercrash",&CpvAccess(_curRestartPhase),"restarting this processor after a crash")){
295 # if CMK_MEM_CHECKPOINT
296 faultFunc = CkMemRestart;
298 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
299 faultFunc = CkMlogRestart;
301 CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
303 #if CMK_MESSAGE_LOGGING
304 // reading +ftc_disk flag
305 if (CmiGetArgFlagDesc(argv, "+ftc_disk", "Disk Checkpointing")) {
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
315 printf("[%d] killFlag set to true for file %s\n",CkMyPe(),killFile);
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"))
326 CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
327 if (_ringtoken > CkNumPes()) _ringtoken = CkNumPes();
330 // if the argument +raiseevac is present then cause faults
331 if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
335 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
336 if(!CmiGetArgIntDesc(argv,"+teamSize",&teamSize,"Set the team size for message logging")){
339 if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
342 if(CmiGetArgIntDesc(argv,"+fastRecovery", ¶llelRecovery, "Parallel recovery with message logging protocol")){
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;
353 /* Anytime migration flag */
354 _isAnytimeMigration = true;
355 if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
356 _isAnytimeMigration = false;
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;
364 _isStaticInsertion = false;
365 if (CmiGetArgFlagDesc(argv,"+staticInsertion","Array elements are only inserted at construction")) {
366 _isStaticInsertion = true;
369 useNodeBlkMapping = false;
370 if (CmiGetArgFlagDesc(argv,"+useNodeBlkMapping","Array elements are block-mapped in SMP-node level")) {
371 useNodeBlkMapping = true;
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") )
401 CkAbort("You specified a control point command line argument, but compiled charm++ without control point support.\n");
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();
426 static inline void _printStats(void)
428 DEBUGF(("[%d] _printStats\n", CkMyPe()));
430 if(_printSS || _printCS) {
431 Stats *total = new Stats();
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());
441 CkPrintf("Total Chares: [%d created, %d processed]\n",
442 total->getCharesCreated(), total->getCharesProcessed());
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());
470 static inline void _printStats(void) {}
473 typedef struct _statsHeader
478 static void * mergeStats(int *size, void *data, void **remote, int count)
481 statsHeader *dataMsg = (statsHeader*)EnvToUsr((envelope*) data), *newDataMsg;
482 int nPes = dataMsg->n, currentIndex = 0;
484 for (int i = 0; i < count; ++i)
486 nPes += ((statsHeader *)EnvToUsr((envelope *)remote[i]))->n;
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)
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;
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);
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;
527 /* General purpose handler for runtime warnings post-execution */
528 static void *mergeWarningMsg(int * size, void * data, void ** remote, int count){
531 WarningMsg *msg = (WarningMsg*)EnvToUsr((envelope*) data), *m;
533 /* Reduction on warning information gained from children */
534 for(i = 0; i < count; ++i)
536 m = (WarningMsg*)EnvToUsr((envelope*) remote[i]);
537 msg->queue_overflow_count += m->queue_overflow_count;
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)
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");
568 #endif /* CMK_LOCKLESS_QUEUE */
570 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
571 extern void _messageLoggingExit();
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);
595 static void _exitHandler(envelope *env)
597 DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
598 switch(env->getMsgtype()) {
600 CkAssert(CkMyPe()==0);
609 CkAssert(CkMyPe()==0);
610 if (!_CkExitFnVec.isEmpty()) {
612 CkExitFn fn = _CkExitFnVec.deq();
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
624 DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
625 const int stride = CkNumPes()/_ringtoken;
627 while (pe<CkNumPes()) {
628 CmiSyncSend(pe, env->getTotalsize(), (char *)env);
633 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
637 ConverseExit(_exitcode);
641 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
642 _messageLoggingExit();
644 DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
645 CkNumberHandler(_charmHandlerIdx,_discardHandler);
646 CkNumberHandler(_bocHandlerIdx, _discardHandler);
648 if(CmiNodeAlive(CkMyPe()))
654 #if CMK_WITH_WARNINGS
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();
668 int stride = CkNumPes()/_ringtoken;
670 if (pe < CkNumPes() && pe % stride != 0)
671 CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
677 #if CMK_SHRINK_EXPAND
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;
691 CkAssert(CkMyPe()==0);
692 statsHeader* header = (statsHeader*)EnvToUsr(env);
694 Stats* currentStats = (Stats*)(header + 1);
695 for (int i = 0; i < n; ++i)
697 _allStats[currentStats->getPe()] = currentStats;
700 DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), n));
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);
710 DEBUGF(("[%d] Calling converse exit from StatDoneMsg \n",CkMyPe()));
711 ConverseExit(_exitcode);
712 if (CharmLibInterOperate)
713 CpvAccess(interopExitFlag) = 1;
716 #if CMK_WITH_WARNINGS
719 CkAssert(CkMyPe()==0);
720 WarningMsg* msg = (WarningMsg*)EnvToUsr(env);
723 envelope* env = _allocEnv(WarnDoneMsg);
724 CmiSetHandler(env, _exitHandlerIdx);
725 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char*)env);
729 DEBUGF(("[%d] Calling converse exit from WarnDoneMsg \n",CkMyPe()));
730 ConverseExit(_exitcode);
731 if (CharmLibInterOperate)
732 CpvAccess(interopExitFlag) = 1;
736 CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
740 #if CMK_SHRINK_EXPAND
741 void _ROGroupRestartHandler(void * msg){
742 CkResumeRestartMain((char *)msg);
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.
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];
760 #if CMK_SHRINK_EXPAND
762 CkPrintf("_processBufferedBocInits: empty message in restart, ignoring\n");
766 CkAbort("_processBufferedBocInits: empty message");
768 CkAbort("_processBufferedBocInits: empty message");
772 CkUnpackMessage(&env);
773 _processBocInitMsg(ck,env);
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.
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");
792 CkUnpackMessage(&env);
793 _processNodeBocInitMsg(ck,env);
798 static inline void _processBufferedMsgs(void)
800 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
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);
807 _processHandler((void *)env, CkpvAccess(_coreState));
809 _processHandler((void *)env, CkpvAccess(_coreState));
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.
827 static void _sendTriggers(void)
830 CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
831 if (!CksvAccess(_triggersSent))
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);
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
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.
858 if (CkpvAccess(_initdone)) return;
859 CkpvAccess(_initdone) = true;
860 DEBUGF(("[%d] _initDone.\n", CkMyPe()));
861 if (!CksvAccess(_triggersSent)) _sendTriggers();
862 CkNumberHandler(_triggerHandlerIdx, _discardHandler);
864 if(CkMyRank() == 0) {
865 _processBufferedNodeBocInits();
866 quietMode = 0; // re-enable CmiPrintf's if they were disabled
868 CmiNodeBarrier(); // wait for all nodegroups to be created
869 _processBufferedBocInits();
870 DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
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.
884 static void _triggerHandler(envelope *env)
886 if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
888 DEBUGF(("Calling Init Done from _triggerHandler\n"));
891 if (env!=NULL) CmiFree(env);
894 static inline void _processROMsgMsg(envelope *env)
897 *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
901 static inline void _processRODataMsg(envelope *env)
903 //Unpack each readonly:
905 PUP::fromMem pu((char *)EnvToUsr(env));
906 for(size_t i=0;i<_readonlyTable.size();i++) {
907 _readonlyTable[i]->pupData(pu);
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)
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
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).
946 static void _initHandler(void *msg, CkCoreState *ck)
948 CkAssert(CkMyPe()!=0);
949 envelope *env = (envelope *) msg;
951 if (ck->watcher!=NULL) {
952 if (!ck->watcher->processMessage(&env,ck)) return;
955 switch (env->getMsgtype()) {
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);
963 (*CkpvAccess(_bocInitVec))[env->getGroupNum().idx] = env;
964 } else _bufferHandler(msg);
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);
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);
979 CkpvAccess(_numInitsRecd)++;
980 CpvAccess(_qd)->process();
981 if(env->isPacked()) CkUnpackMessage(&env);
982 _processROMsgMsg(env);
985 CkpvAccess(_numInitsRecd)++;
986 CpvAccess(_qd)->process();
987 _numExpectInitMsgs = env->getCount();
988 _processRODataMsg(env);
991 CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
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)) {
999 #if CMK_SHRINK_EXPAND
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);
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)
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). */
1049 void EmergencyExit(void) {
1051 /* Delete _coreState to force any CkMessageWatcher to close down. */
1052 if (CkpvAccess(_coreState) != NULL) {
1053 delete CkpvAccess(_coreState);
1054 CkpvAccess(_coreState) = NULL;
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);
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();
1079 extern void LBTopoInit();
1081 extern void _initChareTables();
1082 #if CMK_MEM_CHECKPOINT
1083 extern void init_memcheckpt(char **argv);
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()
1103 if(BgNodeRank()==0) // called only once on an emulating node
1108 for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
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
1129 CmiAssignOnce(&_qdHandlerIdx, CmiRegisterHandler((CmiHandler)_qdHandler));
1130 CmiAssignOnce(&_qdCommHandlerIdx, CmiRegisterHandler((CmiHandler)_qdCommHandler));
1131 if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
1133 CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
1137 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
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".
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);
1183 CpvInitialize(char *,_validProcessors);
1185 CkpvInitialize(char ,startedEvac);
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;
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();
1230 CmiNodeAllBarrier();
1232 #if ! CMK_BIGSIM_CHARM
1233 initQd(argv); // bigsim calls it in ConverseCommonInit
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));
1259 _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1261 CmiAssignOnce(&_triggerHandlerIdx, CkRegisterHandler(_triggerHandler));
1264 CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1266 _futuresModuleInit(); // part of futures implementation is a converse module
1267 _loadbalancerInit();
1268 _metabalancerInit();
1271 if (CmiMyRank() == 0) {
1275 #if CMK_MEM_CHECKPOINT
1276 init_memcheckpt(argv);
1279 initCharmProjections();
1280 #if CMK_TRACE_IN_CHARM
1281 // initialize trace module in ck
1282 traceCharmInit(argv);
1285 CkpvInitialize(int, envelopeEventID);
1286 CkpvAccess(envelopeEventID) = 0;
1287 CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1289 // Set the ack handler function used for the direct nocopy api and the entry method nocopy api
1290 CmiSetDirectNcpyAckHandler(CkRdmaDirectAckHandler);
1292 #if CMK_ONESIDED_IMPL
1293 CmiSetEMNcpyAckHandler(CkRdmaEMAckHandler);
1296 The rank-0 processor of each node calls the
1297 translator-generated "_register" routines.
1299 _register routines call the charm.h "CkRegister*" routines,
1300 which record function pointers and class information for
1301 all Charm entities, like Chares, Arrays, and readonlies.
1303 There's one _register routine generated for each
1304 .ci file. _register routines *must* be called in the
1305 same order on every node, and *must not* be called by
1306 multiple threads simultaniously.
1314 SDAG::registerPUPables();
1315 CmiArgGroup("Charm++",NULL);
1316 _parseCommandLineOpts(argv);
1318 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1319 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1320 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1321 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1322 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1323 CkRegisterChareInCharm(CkIndex_Group::__idx);
1324 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1327 These _register calls are for the built-in
1328 Charm .ci files, like arrays and load balancing.
1329 If you add a .ci file to charm, you'll have to
1330 add a call to the _register routine here, or make
1331 your library into a "-module".
1333 _registerCkFutures();
1335 _registerLBDatabase();
1336 _registerMetaBalancer();
1337 _registerCkCallback();
1339 _registerCkCheckpoint();
1340 _registerCkMulticast();
1341 #if CMK_MEM_CHECKPOINT
1342 _registerCkMemCheckpoint();
1346 Load balancers are currently registered in Charm++ through a C file that is generated and
1347 and compiled by charmc when making an executable. That file contains appropriate calls to
1348 register whatever load balancers are being linked in.
1349 Without an executable (charm4py just uses libcharm.so), the load balancers in libcharm.so
1350 have to somehow be registered during init.
1351 With the planned load balancing framework, load balancer registration will hopefully go away,
1352 at least for strategies used in central/hybrid, because they will stop being chares.
1354 _registerGreedyRefineLB();
1358 CkRegisterMainModule is generated by the (unique)
1359 "mainmodule" .ci file. It will include calls to
1360 register all the .ci files.
1363 CkRegisterMainModule();
1365 // CkRegisterMainModule doesn't exist in charm4py because there is no executable.
1366 // Instead, we go to Python to register user chares from there
1367 if (CkRegisterMainModuleCallback)
1368 CkRegisterMainModuleCallback();
1370 CkAbort("No callback for CkRegisterMainModule");
1374 _registerExternalModules is actually generated by
1375 charmc at link time (as "moduleinit<pid>.C").
1377 This generated routine calls the _register functions
1378 for the .ci files of libraries linked using "-module".
1379 This funny initialization is most useful for AMPI/FEM
1380 programs, which don't have a .ci file and hence have
1381 no other way to control the _register process.
1384 _registerExternalModules(argv);
1388 /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1389 if (CkMyRank() == 0) {
1390 CpdBreakPointInit();
1392 CmiNodeAllBarrier();
1394 // Execute the initcalls registered in modules
1395 _initCallTable.enumerateInitCalls();
1398 CpdFinishInitialization();
1400 if (CkMyRank() == 0)
1402 CmiNodeAllBarrier();
1404 CkpvAccess(_myStats) = new Stats();
1405 CkpvAccess(_msgPool) = new MsgPool();
1407 CmiNodeAllBarrier();
1414 #if CMK_SMP_TRACE_COMMTHREAD
1415 _TRACE_BEGIN_COMPUTATION();
1417 if (!inCommThread) {
1418 _TRACE_BEGIN_COMPUTATION();
1422 #ifdef ADAPT_SCHED_MEM
1424 memCriticalEntries = new int[numMemCriticalEntries];
1426 for(int i=0; i<_entryTable.size(); i++){
1427 if(_entryTable[i]->isMemCritical){
1428 memCriticalEntries[memcnt++] = i;
1434 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1435 _messageLoggingInit();
1440 CpvAccess(_validProcessors) = new char[CkNumPes()];
1441 for(int vProc=0;vProc<CkNumPes();vProc++){
1442 CpvAccess(_validProcessors)[vProc]=1;
1444 CmiAssignOnce(&_ckEvacBcastIdx, CkRegisterHandler(_ckEvacBcast));
1445 CmiAssignOnce(&_ckAckEvacIdx, CkRegisterHandler(_ckAckEvac));
1448 CkpvAccess(startedEvac) = 0;
1450 CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1452 CpvAccess(serializer) = 0;
1454 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1455 CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1460 processRaiseEvacFile(_raiseEvacFile);
1463 // CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1464 CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1467 CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1472 if (CkMyRank() == 0) {
1475 CmiNodeAllBarrier();
1477 if (!_replaySystem) {
1478 CkFtFn faultFunc_restart = CkRestartMain;
1479 if (faultFunc == NULL || faultFunc == faultFunc_restart) { // this is not restart from memory
1480 // these two are blocking calls for non-bigsim
1481 #if ! CMK_BIGSIM_CHARM
1482 CmiInitCPUAffinity(argv);
1483 CmiInitMemAffinity(argv);
1486 CmiInitCPUTopology(argv);
1487 if (CkMyRank() == 0) {
1488 TopoManager_reset(); // initialize TopoManager singleton
1489 #if !CMK_BIGSIM_CHARM
1490 _topoTree = ST_RecursivePartition_getTreeInfo(0);
1493 CmiNodeAllBarrier(); // threads wait until _topoTree has been generated
1494 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1495 if (CmiCpuTopologyEnabled()) {
1498 CmiGetPesOnPhysicalNode(0, &pelist, &num);
1499 #if !CMK_MULTICORE && !CMK_SMP_NO_COMMTHD
1500 // Count communication threads, if present
1501 // XXX: Assuming uniformity of node size here
1502 num += num/CmiMyNodeSize();
1504 if (!_Cmi_forceSpinOnIdle && num > CmiNumCores())
1507 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());
1508 CmiLock(CksvAccess(_nodeLock));
1509 if (! _Cmi_sleepOnIdle) _Cmi_sleepOnIdle = 1;
1510 CmiUnlock(CksvAccess(_nodeLock));
1517 if (CmiMyRank() == 0) {
1522 // ensure HAPI is initialized before registering callback functions
1523 if (CmiMyRank() < CmiMyNodeSize()) {
1526 hapiRegisterCallbacks();
1529 if(CmiMyPe() == 0) {
1531 if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name"))
1533 std::stringstream sstm;
1534 sstm << topoFilename << "." << CmiMyPartition();
1535 std::string result = sstm.str();
1537 fp = fopen(result.c_str(), "w");
1539 CkPrintf("Error opening %s file, writing to stdout\n", topoFilename);
1542 TopoManager_printAllocation(fp);
1547 #if CMK_USE_PXSHM && ( CMK_CRAYXE || CMK_CRAYXC ) && CMK_SMP
1548 // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized
1549 // again after cpuaffinity is done
1550 if (CkMyRank() == 0) {
1553 CmiNodeAllBarrier();
1557 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1558 // Register the BG handler for CCS. Notice that this is put into a variable shared by
1559 // the whole real processor. This because converse needs to find it. We check that all
1560 // virtual processors register the same index for this handler.
1566 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1568 if (!inCommThread) {
1569 CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0, GroupDepNum{});
1570 msg->argc = CmiGetArgc(argv);
1572 faultFunc(_restartDir, msg);
1575 }else if(CkMyPe()==0){
1577 _allStats = new Stats*[CkNumPes()];
1579 size_t i, nMains=_mainTable.size();
1581 // Check CkArgMsg and warn if it contains any args starting with '+'.
1582 // These args may be args intended for Charm++ but because of the specific
1583 // build, were not parsed by the RTS.
1585 int argc = CmiGetArgc(argv);
1586 for (int i = 1; i < argc; i++) {
1587 // The +vp option for TCharm is a special case that needs to be checked
1588 // separately, because the number passed does not need a space after
1589 // the vp, and the option can be specified with a '+' or a '-'.
1590 if (strncmp(argv[i],"+vp",3) == 0) {
1591 if (_optSet.count("+vp") == 0) {
1593 CmiPrintf("WARNING: %s is a TCharm command line argument, but you have not compiled with TCharm\n", argv[i]);
1595 } else if (strncmp(argv[i],"-vp",3) == 0) {
1596 CmiPrintf("WARNING: %s is no longer valid because -vp has been deprecated. Please use +vp.\n", argv[i]);
1597 } else if (argv[i][0] == '+' && _optSet.count(argv[i]) == 0) {
1599 CmiPrintf("WARNING: %s is a command line argument beginning with a '+' but was not parsed by the RTS.\n", argv[i]);
1600 } else if (argv[i][0] == '+' && _optSet.count(argv[i]) != 0) {
1601 fprintf(stderr,"%s is used more than once. Please remove duplicate arguments.\n", argv[i]);
1602 CmiAbort("Bad command-line argument\n");
1606 CmiPrintf("If any of the above arguments were intended for the RTS you may need to recompile Charm++ with different options.\n");
1609 CmiCheckAffinity(); // check for thread oversubscription
1611 for(i=0;i<nMains;i++) /* Create all mainchares */
1613 size_t size = _chareTable[_mainTable[i]->chareIdx]->size;
1614 void *obj = malloc(size);
1616 _mainTable[i]->setObj(obj);
1617 CkpvAccess(_currentChare) = obj;
1618 CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1619 CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0, GroupDepNum{});
1620 msg->argc = CmiGetArgc(argv);
1622 quietMode = 0; // allow printing any mainchare user messages
1623 _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1624 if (quietModeRequested) quietMode = 1;
1625 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1626 CpvAccess(_currentObj) = (Chare *)obj;
1631 _STATS_RECORD_CREATE_CHARE_N(nMains);
1632 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1637 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1639 void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1642 //Pack the message and send it to all other processors
1643 envelope *env = UsrToEnv(roMsg);
1644 env->setSrcPe(CkMyPe());
1645 env->setMsgtype(ROMsgMsg);
1647 CmiSetHandler(env, _initHandlerIdx);
1648 CkPackMessage(&env);
1649 CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1650 CpvAccess(_qd)->create(CkNumPes()-1);
1652 //For processor 0, unpack and re-set the global
1653 CkUnpackMessage(&env);
1654 _processROMsgMsg(env);
1658 //Determine the size of the RODataMessage
1660 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1662 //Allocate and fill out the RODataMessage
1663 envelope *env = _allocEnv(RODataMsg, ps.size());
1664 PUP::toMem pp((char *)EnvToUsr(env));
1665 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1667 env->setCount(++_numInitMsgs);
1668 env->setSrcPe(CkMyPe());
1669 CmiSetHandler(env, _initHandlerIdx);
1670 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1671 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1672 CpvAccess(_qd)->create(CkNumPes()-1);
1675 // check for thread oversubscription
1677 // NOTE: this assumes commthreads will not block from this point on
1680 DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1681 // when I am a communication thread, I don't participate initDone.
1683 CkNumberHandlerEx(_bocHandlerIdx, _processHandler, CkpvAccess(_coreState));
1684 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
1685 _processBufferedMsgs();
1689 // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1690 if (CpvAccess(cpdSuspendStartup))
1692 //CmiPrintf("In Parallel Debugging mode .....\n");
1706 int charm_main(int argc, char **argv)
1709 memory_stack_top = &stack_top;
1711 ConverseInit(argc, argv, (CmiStartFn) _initCharm, 0, 0);
1716 void FTN_NAME(CHARM_MAIN_FORTRAN_WRAPPER, charm_main_fortran_wrapper)(int *argc, char **argv)
1718 charm_main(*argc, argv);
1721 // user callable function to register an exit function, this function
1722 // will perform task of collecting of info from all pes to pe0, and call
1723 // CkContinueExit() on pe0 again to recursively traverse the registered exitFn.
1724 // see trace-summary for an example.
1725 void registerExitFn(CkExitFn fn)
1727 #if CMK_SHRINK_EXPAND
1728 CkAbort("registerExitFn is called when shrink-expand is enabled!");
1730 _CkExitFnVec.enq(fn);