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