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"
75 #include "cuda-hybrid-api.h"
78 void CkRestartMain(const char* dirname, CkArgMsg* args);
80 #define DEBUGF(x) //CmiPrintf x;
82 #include "TopoManager.h"
84 UChar _defaultQueueing = CK_QUEUEING_FIFO;
90 * This value has the number of total initialization message a processor awaits.
91 * It is received on nodes other than zero together with the ROData message.
92 * Even though it is shared by all processors it is ok: it doesn't matter when and
93 * by who it is set, provided that it becomes equal to the number of awaited messages
94 * (which is always at least one ---the readonly data message).
96 UInt _numExpectInitMsgs = 0;
98 * This number is used only by processor zero to count how many messages it will
99 * send out for the initialization process. After the readonly data message is sent
100 * (containing this counter), its value becomes irrelevant.
102 UInt _numInitMsgs = 0;
104 * Count the number of nodegroups that have been created in mainchares.
105 * Since the nodegroup creation is executed by a single processor in a
106 * given node, this value must be seen by all processors in a node.
108 CksvDeclare(UInt,_numInitNodeMsgs);
110 int _charmHandlerIdx;
112 int _roRestartHandlerIdx;
115 int _qdCommHandlerIdx;
116 int _triggerHandlerIdx;
117 bool _mainDone = false;
118 CksvDeclare(bool, _triggersSent);
124 CkpvDeclare(void*, _currentChare);
125 CkpvDeclare(int, _currentChareType);
126 CkpvDeclare(CkGroupID, _currentGroup);
127 CkpvDeclare(void*, _currentNodeGroupObj);
128 CkpvDeclare(CkGroupID, _currentGroupRednMgr);
129 CkpvDeclare(GroupTable*, _groupTable);
130 CkpvDeclare(GroupIDTable*, _groupIDTable);
131 CkpvDeclare(CmiImmediateLockType, _groupTableImmLock);
132 CkpvDeclare(UInt, _numGroups);
134 CkpvDeclare(CkCoreState *, _coreState);
136 CksvDeclare(UInt, _numNodeGroups);
137 CksvDeclare(GroupTable*, _nodeGroupTable);
138 CksvDeclare(GroupIDTable, _nodeGroupIDTable);
139 CksvDeclare(CmiImmediateLockType, _nodeGroupTableImmLock);
140 CksvDeclare(CmiNodeLock, _nodeLock);
141 CksvStaticDeclare(PtrVec*,_nodeBocInitVec);
142 CkpvDeclare(int, _charmEpoch);
144 CkpvDeclare(bool, _destroyingNodeGroup);
147 CkpvDeclare(Stats*, _myStats);
148 CkpvDeclare(MsgPool*, _msgPool);
150 CkpvDeclare(_CkOutStream*, _ckout);
151 CkpvDeclare(_CkErrStream*, _ckerr);
153 CkpvStaticDeclare(int, _numInitsRecd);
154 CkpvStaticDeclare(bool, _initdone);
155 CkpvStaticDeclare(PtrQ*, _buffQ);
156 CkpvStaticDeclare(PtrVec*, _bocInitVec);
158 //for interoperability
159 extern void _libExitHandler(envelope *env);
160 extern int _libExitHandlerIdx;
161 CpvCExtern(int,interopExitFlag);
163 #if CMK_SHRINK_EXPAND
164 //for shrink expand cleanup
165 int _ROGroupRestartHandlerIdx;
166 const char* _shrinkexpand_basedir;
171 CpvCExtern(char *, _validProcessors);
172 CkpvDeclare(char ,startedEvac);
177 static Stats** _allStats = 0;
179 static bool _exitStarted = 0;
181 static InitCallTable _initCallTable;
184 #define _STATS_ON(x) (x) = 1
186 #define _STATS_ON(x) \
187 if (CkMyPe()==0) CmiPrintf("stats unavailable in optimized version. ignoring...\n");
191 typedef void (*CkFtFn)(const char *, CkArgMsg *);
192 static CkFtFn faultFunc = NULL;
193 static char* _restartDir;
195 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
197 int chkptPeriod=1000;
198 bool fastRecovery = false;
199 int parallelRecovery = 1;
200 extern int BUFFER_TIME; //time spent waiting for buffered messages
203 // flag for killing processes
204 extern bool killFlag;
205 // file specifying the processes to be killed
206 extern char *killFile;
207 // function for reading the kill file
209 #if CMK_MESSAGE_LOGGING
210 // flag for disk checkpoint
211 extern bool diskCkptFlag;
214 int _defaultObjectQ = 0; // for obejct queue
215 bool _ringexit = 0; // for charm exit
217 extern int _messageBufferingThreshold;
223 flag which marks whether or not to trigger the processor shutdowns
225 static bool _raiseEvac=0;
226 static char *_raiseEvacFile;
227 void processRaiseEvacFile(char *raiseEvacFile);
229 extern bool useNodeBlkMapping;
231 extern "C" int quietMode;
232 extern "C" int quietModeRequested;
234 // Modules are required to register command line opts they will parse. These
235 // options are stored in the _optSet, and then when parsing command line opts
236 // users will be warned about options starting with a '+' that are not in this
237 // table. This usually implies that they are attempting to use a Charm++ option
238 // without having compiled Charm++ to use the module that options belongs to.
239 std::set<std::string> _optSet;
240 void _registerCommandLineOpt(const char* opt) {
241 // The command line options are only checked during init on PE0, so this makes
242 // thread safety easy.
248 static inline void _parseCommandLineOpts(char **argv)
250 if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
252 if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
254 if (CmiGetArgFlagDesc(argv,"+fifo", "Default to FIFO queuing"))
255 _defaultQueueing = CK_QUEUEING_FIFO;
256 if (CmiGetArgFlagDesc(argv,"+lifo", "Default to LIFO queuing"))
257 _defaultQueueing = CK_QUEUEING_LIFO;
258 if (CmiGetArgFlagDesc(argv,"+ififo", "Default to integer-prioritized FIFO queuing"))
259 _defaultQueueing = CK_QUEUEING_IFIFO;
260 if (CmiGetArgFlagDesc(argv,"+ilifo", "Default to integer-prioritized LIFO queuing"))
261 _defaultQueueing = CK_QUEUEING_ILIFO;
262 if (CmiGetArgFlagDesc(argv,"+bfifo", "Default to bitvector-prioritized FIFO queuing"))
263 _defaultQueueing = CK_QUEUEING_BFIFO;
264 if (CmiGetArgFlagDesc(argv,"+blifo", "Default to bitvector-prioritized LIFO queuing"))
265 _defaultQueueing = CK_QUEUEING_BLIFO;
266 if (CmiGetArgFlagDesc(argv,"+objq", "Default to use object queue for every obejct"))
268 #if CMK_OBJECT_QUEUE_AVAILABLE
271 CmiPrintf("Charm++> Create object queue for every Charm object.\n");
273 CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
277 #if CMK_SHRINK_EXPAND
278 if (!CmiGetArgStringDesc(argv, "+shrinkexpand_basedir", (char **)&_shrinkexpand_basedir,
279 "Checkpoint directory used for shrink-expand (defaults to /dev/shm)"))
280 _shrinkexpand_basedir = "/dev/shm";
283 if(CmiGetArgString(argv,"+restart",&_restartDir))
284 faultFunc = CkRestartMain;
286 if (CmiGetArgIntDesc(argv,"+restartaftercrash",&CpvAccess(_curRestartPhase),"restarting this processor after a crash")){
287 # if CMK_MEM_CHECKPOINT
288 faultFunc = CkMemRestart;
290 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
291 faultFunc = CkMlogRestart;
293 CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
295 #if CMK_MESSAGE_LOGGING
296 // reading +ftc_disk flag
297 if (CmiGetArgFlagDesc(argv, "+ftc_disk", "Disk Checkpointing")) {
301 // reading the killFile
302 if(CmiGetArgStringDesc(argv,"+killFile", &killFile,"Generates SIGKILL on specified processors")){
303 if(faultFunc == NULL){
304 //do not read the killfile if this is a restarting processor
307 printf("[%d] killFlag set to true for file %s\n",CkMyPe(),killFile);
313 // shut down program in ring fashion to allow projections output w/o IO error
314 if (CmiGetArgIntDesc(argv,"+ringexit",&_ringtoken, "Program exits in a ring fashion"))
318 CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
319 if (_ringtoken > CkNumPes()) _ringtoken = CkNumPes();
324 if the argument +raiseevac is present then cause faults
326 if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
329 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
330 if(!CmiGetArgIntDesc(argv,"+teamSize",&teamSize,"Set the team size for message logging")){
333 if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
336 if(CmiGetArgIntDesc(argv,"+fastRecovery", ¶llelRecovery, "Parallel recovery with message logging protocol")){
341 if (!CmiGetArgIntDesc(argv, "+messageBufferingThreshold",
342 &_messageBufferingThreshold,
343 "Message size above which the runtime will buffer messages directed at unlocated array elements")) {
344 _messageBufferingThreshold = INT_MAX;
347 /* Anytime migration flag */
348 _isAnytimeMigration = true;
349 if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
350 _isAnytimeMigration = false;
353 _isNotifyChildInRed = true;
354 if (CmiGetArgFlagDesc(argv,"+noNotifyChildInReduction","The program has at least one element per processor for each charm array created")) {
355 _isNotifyChildInRed = false;
358 _isStaticInsertion = false;
359 if (CmiGetArgFlagDesc(argv,"+staticInsertion","Array elements are only inserted at construction")) {
360 _isStaticInsertion = true;
363 useNodeBlkMapping = false;
364 if (CmiGetArgFlagDesc(argv,"+useNodeBlkMapping","Array elements are block-mapped in SMP-node level")) {
365 useNodeBlkMapping = true;
368 #if ! CMK_WITH_CONTROLPOINT
369 // Display a warning if charm++ wasn't compiled with control point support but user is expecting it
370 if( CmiGetArgFlag(argv,"+CPSamplePeriod") ||
371 CmiGetArgFlag(argv,"+CPSamplePeriodMs") ||
372 CmiGetArgFlag(argv,"+CPSchemeRandom") ||
373 CmiGetArgFlag(argv,"+CPExhaustiveSearch") ||
374 CmiGetArgFlag(argv,"+CPAlwaysUseDefaults") ||
375 CmiGetArgFlag(argv,"+CPSimulAnneal") ||
376 CmiGetArgFlag(argv,"+CPCriticalPathPrio") ||
377 CmiGetArgFlag(argv,"+CPBestKnown") ||
378 CmiGetArgFlag(argv,"+CPSteering") ||
379 CmiGetArgFlag(argv,"+CPMemoryAware") ||
380 CmiGetArgFlag(argv,"+CPSimplex") ||
381 CmiGetArgFlag(argv,"+CPDivideConquer") ||
382 CmiGetArgFlag(argv,"+CPLDBPeriod") ||
383 CmiGetArgFlag(argv,"+CPLDBPeriodLinear") ||
384 CmiGetArgFlag(argv,"+CPLDBPeriodQuadratic") ||
385 CmiGetArgFlag(argv,"+CPLDBPeriodOptimal") ||
386 CmiGetArgFlag(argv,"+CPDefaultValues") ||
387 CmiGetArgFlag(argv,"+CPGatherAll") ||
388 CmiGetArgFlag(argv,"+CPGatherMemoryUsage") ||
389 CmiGetArgFlag(argv,"+CPGatherUtilization") ||
390 CmiGetArgFlag(argv,"+CPSaveData") ||
391 CmiGetArgFlag(argv,"+CPNoFilterData") ||
392 CmiGetArgFlag(argv,"+CPLoadData") ||
393 CmiGetArgFlag(argv,"+CPDataFilename") )
395 CkAbort("You specified a control point command line argument, but compiled charm++ without control point support.\n");
401 static void _bufferHandler(void *msg)
403 DEBUGF(("[%d] _bufferHandler called.\n", CkMyPe()));
404 CkpvAccess(_buffQ)->enq(msg);
407 static void _discardHandler(envelope *env)
409 // MESSAGE_PHASE_CHECK(env);
411 DEBUGF(("[%d] _discardHandler called.\n", CkMyPe()));
412 #if CMK_MEM_CHECKPOINT
413 //CkPrintf("[%d] _discardHandler called!\n", CkMyPe());
414 if (CkInRestarting()) CpvAccess(_qd)->process();
420 static inline void _printStats(void)
422 DEBUGF(("[%d] _printStats\n", CkMyPe()));
424 if(_printSS || _printCS) {
425 Stats *total = new Stats();
427 for(i=0;i<CkNumPes();i++)
428 total->combine(_allStats[i]);
429 CkPrintf("Charm Kernel Summary Statistics:\n");
430 for(i=0;i<CkNumPes();i++) {
431 CkPrintf("Proc %d: [%d created, %d processed]\n", i,
432 _allStats[i]->getCharesCreated(),
433 _allStats[i]->getCharesProcessed());
435 CkPrintf("Total Chares: [%d created, %d processed]\n",
436 total->getCharesCreated(), total->getCharesProcessed());
439 CkPrintf("Charm Kernel Detailed Statistics (R=requested P=processed):\n\n");
441 CkPrintf(" Create Mesgs Create Mesgs Create Mesgs\n");
442 CkPrintf(" Chare for Group for Nodegroup for\n");
443 CkPrintf("PE R/P Mesgs Chares Mesgs Groups Mesgs Nodegroups\n");
444 CkPrintf("---- --- --------- --------- --------- --------- --------- ----------\n");
446 for(i=0;i<CkNumPes();i++) {
447 CkPrintf("%4d R %9d %9d %9d %9d %9d %9d\n P %9d %9d %9d %9d %9d %9d\n",i,
448 _allStats[i]->getCharesCreated(),
449 _allStats[i]->getForCharesCreated(),
450 _allStats[i]->getGroupsCreated(),
451 _allStats[i]->getGroupMsgsCreated(),
452 _allStats[i]->getNodeGroupsCreated(),
453 _allStats[i]->getNodeGroupMsgsCreated(),
454 _allStats[i]->getCharesProcessed(),
455 _allStats[i]->getForCharesProcessed(),
456 _allStats[i]->getGroupsProcessed(),
457 _allStats[i]->getGroupMsgsProcessed(),
458 _allStats[i]->getNodeGroupsProcessed(),
459 _allStats[i]->getNodeGroupMsgsProcessed());
464 static inline void _printStats(void) {}
467 typedef struct _statsHeader
472 static void * mergeStats(int *size, void *data, void **remote, int count)
475 statsHeader *dataMsg = (statsHeader*)EnvToUsr((envelope*) data), *newDataMsg;
476 int nPes = dataMsg->n, currentIndex = 0;
478 for (int i = 0; i < count; ++i)
480 nPes += ((statsHeader *)EnvToUsr((envelope *)remote[i]))->n;
483 newData = _allocEnv(StatMsg, sizeof(statsHeader) + sizeof(Stats)*nPes);
484 *size = newData->getTotalsize();
485 newDataMsg = (statsHeader *)EnvToUsr(newData);
486 newDataMsg->n = nPes;
488 statsHeader *current = dataMsg;
489 Stats *currentStats = (Stats*)(current + 1), *destination = (Stats*)(newDataMsg + 1);
490 memcpy(destination + currentIndex, currentStats, sizeof(Stats) * current->n);
491 currentIndex += current->n;
493 for (int i = 0; i < count; ++i)
495 current = ((statsHeader *)EnvToUsr((envelope *)remote[i]));
496 currentStats = (Stats *)(current + 1);
497 memcpy(destination + currentIndex, currentStats, sizeof(Stats) * current->n);
498 currentIndex += current->n;
505 static inline void _sendStats(void)
507 DEBUGF(("[%d] _sendStats\n", CkMyPe()));
508 envelope *env = _allocEnv(StatMsg, sizeof(statsHeader) + sizeof(Stats));
509 statsHeader* msg = (statsHeader*)EnvToUsr(env);
511 memcpy(msg+1, CkpvAccess(_myStats), sizeof(Stats));
512 CmiSetHandler(env, _exitHandlerIdx);
513 CmiReduce(env, env->getTotalsize(), mergeStats);
516 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
517 extern void _messageLoggingExit();
521 //CpvExtern(int, CldHandlerIndex);
522 //extern "C" void CldHandler(char *);
523 extern int index_skipCldHandler;
524 extern void _skipCldHandler(void *converseMsg);
526 void _discard_charm_message()
528 CkNumberHandler(_charmHandlerIdx,_discardHandler);
529 // CkNumberHandler(CpvAccess(CldHandlerIndex), _discardHandler);
530 CkNumberHandler(index_skipCldHandler, _discardHandler);
533 void _resume_charm_message()
535 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
536 // CkNumberHandler(CpvAccess(CldHandlerIndex), CldHandler);
537 CkNumberHandler(index_skipCldHandler, _skipCldHandler);
541 static void _exitHandler(envelope *env)
543 DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
544 switch(env->getMsgtype()) {
546 CkAssert(CkMyPe()==0);
547 if (!_CkExitFnVec.isEmpty()) {
548 CkExitFn fn = _CkExitFnVec.deq();
554 CkAssert(CkMyPe()==0);
560 CkNumberHandler(_charmHandlerIdx,_discardHandler);
561 CkNumberHandler(_bocHandlerIdx, _discardHandler);
562 #if !CMK_BIGSIM_THREAD
563 env->setMsgtype(ReqStatMsg);
564 env->setSrcPe(CkMyPe());
565 // if exit in ring, instead of broadcasting, send in ring
567 DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
568 const int stride = CkNumPes()/_ringtoken;
570 while (pe<CkNumPes()) {
571 CmiSyncSend(pe, env->getTotalsize(), (char *)env);
576 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
584 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
585 _messageLoggingExit();
587 DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
588 CkNumberHandler(_charmHandlerIdx,_discardHandler);
589 CkNumberHandler(_bocHandlerIdx, _discardHandler);
591 if(CmiNodeAlive(CkMyPe())){
595 _mainDone = true; // This is needed because the destructors for
596 // readonly variables will be called when the program
597 // exits. If the destructor is called while _mainDone
598 // is false, it will assume that the readonly variable was
599 // declared locally. On all processors other than 0,
600 // _mainDone is never set to true before the program exits.
601 #if CMK_TRACE_ENABLED
602 if (_ringexit) traceClose();
606 int stride = CkNumPes()/_ringtoken;
608 if (pe < CkNumPes() && pe % stride != 0)
609 CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
615 #if CMK_SHRINK_EXPAND
618 //everyone exits here - there may be issues with leftover messages in the queue
620 DEBUGF(("[%d] Calling converse exit from ReqStatMsg \n",CkMyPe()));
622 if(CharmLibInterOperate)
623 CpvAccess(interopExitFlag) = 1;
629 CkAssert(CkMyPe()==0);
630 statsHeader* header = (statsHeader*)EnvToUsr(env);
632 Stats* currentStats = (Stats*)(header + 1);
633 for (int i = 0; i < n; ++i)
635 _allStats[currentStats->getPe()] = currentStats;
638 DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), n));
641 // broadcast to all others that they can now exit
642 envelope* env = _allocEnv(StatDoneMsg);
643 CmiSetHandler(env, _exitHandlerIdx);
644 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char*)env);
649 DEBUGF(("[%d] Calling converse exit from StatDoneMsg \n",CkMyPe()));
651 if (CharmLibInterOperate)
652 CpvAccess(interopExitFlag) = 1;
656 CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
660 #if CMK_SHRINK_EXPAND
661 void _ROGroupRestartHandler(void * msg){
662 CkResumeRestartMain((char *)msg);
667 * Create all groups in this processor (not called on processor zero).
668 * Notice that only groups created in mainchares are processed here;
669 * groups created later are processed as regular messages.
671 static inline void _processBufferedBocInits(void)
673 CkCoreState *ck = CkpvAccess(_coreState);
674 CkNumberHandlerEx(_bocHandlerIdx,_processHandler, ck);
675 PtrVec &inits=*CkpvAccess(_bocInitVec);
676 int len = inits.size();
677 for(int i=1; i<len; i++) {
678 envelope *env = inits[i];
680 #if CMK_SHRINK_EXPAND
682 CkPrintf("_processBufferedBocInits: empty message in restart, ignoring\n");
686 CkAbort("_processBufferedBocInits: empty message");
688 CkAbort("_processBufferedBocInits: empty message");
692 CkUnpackMessage(&env);
693 _processBocInitMsg(ck,env);
699 * Create all nodegroups in this node (called only by rank zero, and never on node zero).
700 * Notice that only nodegroups created in mainchares are processed here;
701 * nodegroups created later are processed as regular messages.
703 static inline void _processBufferedNodeBocInits(void)
705 CkCoreState *ck = CkpvAccess(_coreState);
706 PtrVec &inits=*CksvAccess(_nodeBocInitVec);
707 int len = inits.size();
708 for(int i=1; i<len; i++) {
709 envelope *env = inits[i];
710 if(env==0) CkAbort("_processBufferedNodeBocInits: empty message");
712 CkUnpackMessage(&env);
713 _processNodeBocInitMsg(ck,env);
718 static inline void _processBufferedMsgs(void)
720 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
722 while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
723 if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
724 if(env->isForAnyPE())
725 _CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
727 _processHandler((void *)env, CkpvAccess(_coreState));
729 _processHandler((void *)env, CkpvAccess(_coreState));
734 static int _charmLoadEstimator(void)
736 return CkpvAccess(_buffQ)->length();
740 * This function is used to send other processors on the same node a signal so
741 * they can check if their _initDone can be called: the reason for this is that
742 * the check at the end of _initHandler can fail due to a missing message containing
743 * a Nodegroup creation. When that message arrives only one processor will receive
744 * it, and thus if no notification is sent to the other processors in the node, they
745 * will never proceed.
747 static void _sendTriggers(void)
750 CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
751 if (!CksvAccess(_triggersSent))
753 CksvAccess(_triggersSent) = true;
754 num = CmiMyNodeSize();
755 envelope *env = _allocEnv(RODataMsg); // Notice that the type here is irrelevant
756 env->setSrcPe(CkMyPe());
757 CmiSetHandler(env, _triggerHandlerIdx);
758 first = CmiNodeFirst(CmiMyNode());
759 for (i=0; i < num; i++)
760 if(first+i != CkMyPe())
761 CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
764 CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
768 * This function (not a handler) is called once and only once per processor.
769 * It signals the processor that the initialization is done and regular messages
772 * On processor zero it is called by _initCharm, on all other processors either
773 * by _initHandler or _triggerHandler (cannot be both).
774 * When fault-tolerance is active, it is called by the fault-tolerance scheme itself.
778 if (CkpvAccess(_initdone)) return;
779 CkpvAccess(_initdone) = true;
780 DEBUGF(("[%d] _initDone.\n", CkMyPe()));
781 if (!CksvAccess(_triggersSent)) _sendTriggers();
782 CkNumberHandler(_triggerHandlerIdx, _discardHandler);
784 if(CkMyRank() == 0) {
785 _processBufferedNodeBocInits();
786 quietMode = 0; // re-enable CmiPrintf's if they were disabled
788 CmiNodeBarrier(); // wait for all nodegroups to be created
789 _processBufferedBocInits();
790 DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
792 DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
793 _processBufferedMsgs();
794 CkpvAccess(_charmEpoch)=1;
798 * Converse handler receiving a signal from another processors in the same node.
799 * (On _sendTrigger there is the explanation of why this is necessary)
800 * Simply check if with the NodeGroup processed by another processor we reached
801 * the expected count. Notice that it can only be called before _initDone: after
802 * _initDone, a message destined for this handler will go instead to the _discardHandler.
804 static void _triggerHandler(envelope *env)
806 if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
808 DEBUGF(("Calling Init Done from _triggerHandler\n"));
811 if (env!=NULL) CmiFree(env);
814 static inline void _processROMsgMsg(envelope *env)
817 *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
821 static inline void _processRODataMsg(envelope *env)
823 //Unpack each readonly:
825 PUP::fromMem pu((char *)EnvToUsr(env));
826 for(size_t i=0;i<_readonlyTable.size();i++) {
827 _readonlyTable[i]->pupData(pu);
834 * This is similar to the _initHandler, only that the Groups and Nodegroups are
835 * initialized from disk, so only one single message is expected.
837 * It is unclear how Readonly Messages are treated during restart... (if at all considered)
839 static void _roRestartHandler(void *msg)
841 CkAssert(CkMyPe()!=0);
842 envelope *env = (envelope *) msg;
843 CkpvAccess(_numInitsRecd)++;
844 _numExpectInitMsgs = env->getCount();
845 _processRODataMsg(env);
846 // in SMP, potentially there us a race condition between rank0 calling
847 // initDone, which sendTriggers, and PE 0 calls bdcastRO which broadcast
849 // if this readonly message arrives later, we need to call trigger again
850 // to trigger initDone() on all ranks
851 // we therefore needs to make sure initDone() is exactly
852 _triggerHandler(NULL);
856 * This handler is used only during initialization. It receives messages from
857 * processor zero regarding Readonly Data (in one single message), Readonly Messages,
858 * Groups, and Nodegroups.
859 * The Readonly Data message also contains the total number of messages expected
860 * during the initialization phase.
861 * For Groups and Nodegroups, only messages with epoch=0 (meaning created from within
862 * a mainchare) are buffered for special creation, the other messages are buffered
863 * together with all the other regular messages by _bufferHandler (and will be flushed
864 * after all the initialization messages have been processed).
866 static void _initHandler(void *msg, CkCoreState *ck)
868 CkAssert(CkMyPe()!=0);
869 envelope *env = (envelope *) msg;
871 if (ck->watcher!=NULL) {
872 if (!ck->watcher->processMessage(&env,ck)) return;
875 switch (env->getMsgtype()) {
877 if (env->getGroupEpoch()==0) {
878 CkpvAccess(_numInitsRecd)++;
879 // _processBocInitMsg already handles QD
880 //CpvAccess(_qd)->process();
881 CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
882 } else _bufferHandler(msg);
885 if (env->getGroupEpoch()==0) {
886 CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
887 CksvAccess(_numInitNodeMsgs)++;
888 CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
889 CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
890 CpvAccess(_qd)->process();
891 } else _bufferHandler(msg);
894 CkpvAccess(_numInitsRecd)++;
895 CpvAccess(_qd)->process();
896 if(env->isPacked()) CkUnpackMessage(&env);
897 _processROMsgMsg(env);
900 CkpvAccess(_numInitsRecd)++;
901 CpvAccess(_qd)->process();
902 _numExpectInitMsgs = env->getCount();
903 _processRODataMsg(env);
906 CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
908 DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
909 if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
915 /*****************************************
917 * ***************************************/
921 CmiAssert(CkMyPe() == 0);
922 // Shuts down Converse handlers for the upper layers on this processor
924 CkNumberHandler(_charmHandlerIdx,_discardHandler);
925 CkNumberHandler(_bocHandlerIdx, _discardHandler);
926 DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
931 envelope *env = _allocEnv(ReqStatMsg);
932 env->setSrcPe(CkMyPe());
933 CmiSetHandler(env, _exitHandlerIdx);
935 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
937 envelope *env = _allocEnv(ExitMsg);
938 env->setSrcPe(CkMyPe());
939 CmiSetHandler(env, _exitHandlerIdx);
940 CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
942 #if ! CMK_BIGSIM_THREAD
943 _TRACE_END_EXECUTE();
944 //Wait for stats, which will call ConverseExit when finished:
950 #if CMK_SHRINK_EXPAND
954 // always send to PE 0
955 envelope *env = _allocEnv(StartExitMsg);
956 env->setSrcPe(CkMyPe());
957 CmiSetHandler(env, _exitHandlerIdx);
958 CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
962 CkQ<CkExitFn> _CkExitFnVec;
964 // triger exit on PE 0,
965 // which traverses _CkExitFnVec to call every registered user exit functions.
966 // Every user exit functions should end with CkExit() to continue the chain
971 DEBUGF(("[%d] CkExit called \n",CkMyPe()));
972 // always send to PE 0
973 envelope *env = _allocEnv(StartExitMsg);
974 env->setSrcPe(CkMyPe());
975 CmiSetHandler(env, _exitHandlerIdx);
976 CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
978 #if ! CMK_BIGSIM_THREAD
979 _TRACE_END_EXECUTE();
980 //Wait for stats, which will call ConverseExit when finished:
981 if(!CharmLibInterOperate)
986 /* This is a routine called in case the application is closing due to a signal.
987 Tear down structures that must be cleaned up even when unclean exit happens.
988 It is called by the machine layer whenever some problem occurs (it is thus up
989 to the machine layer to call this function). */
991 void EmergencyExit(void) {
993 /* Delete _coreState to force any CkMessageWatcher to close down. */
994 if (CkpvAccess(_coreState) != NULL) {
995 delete CkpvAccess(_coreState);
996 CkpvAccess(_coreState) = NULL;
1001 static void _nullFn(void *, void *)
1003 CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
1006 extern void _registerLBDatabase(void);
1007 extern void _registerMetaBalancer(void);
1008 extern void _registerPathHistory(void);
1009 #if CMK_WITH_CONTROLPOINT
1010 extern void _registerControlPoints(void);
1012 extern void _registerTraceControlPoints();
1013 extern void _registerExternalModules(char **argv);
1014 extern void _ckModuleInit(void);
1015 extern void _loadbalancerInit();
1016 extern void _metabalancerInit();
1017 #if CMK_SMP && CMK_TASKQUEUE
1018 extern void _taskqInit();
1020 extern void _initChareTables();
1021 #if CMK_MEM_CHECKPOINT
1022 extern void init_memcheckpt(char **argv);
1024 extern "C" void initCharmProjections();
1025 extern "C" void CmiInitCPUTopology(char **argv);
1026 extern "C" void CmiInitCPUAffinity(char **argv);
1027 extern "C" void CmiInitMemAffinity(char **argv);
1028 extern "C" void CmiInitPxshm(char **argv);
1030 //extern "C" void CldCallback();
1032 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
1034 if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
1035 else _initCallTable.initProcCalls.enq(fn);
1038 void InitCallTable::enumerateInitCalls()
1042 if(BgNodeRank()==0) // called only once on an emulating node
1047 for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
1049 // initproc may depend on initnode calls.
1050 CmiNodeAllBarrier();
1051 for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
1054 CpvCExtern(int, cpdSuspendStartup);
1055 extern "C" void CpdFreeze(void);
1057 extern int _dummy_dq;
1059 extern "C" void initQd(char **argv)
1061 CpvInitialize(QdState*, _qd);
1062 CpvAccess(_qd) = new QdState();
1063 if (CmiMyRank() == 0) {
1064 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
1065 CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
1068 _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
1069 _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
1070 if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
1072 CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
1076 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1079 void CpdBreakPointInit();
1082 This is the main charm setup routine. It's called
1083 on all processors after Converse initialization.
1084 This routine gets passed to Converse from "main.C".
1086 The main purpose of this routine is to set up the objects
1087 and Ckpv's used during a regular Charm run. See the comment
1088 at the top of the file for overall flow.
1090 void _initCharm(int unused_argc, char **argv)
1092 int inCommThread = (CmiMyRank() == CmiMyNodeSize());
1094 DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
1096 CkpvInitialize(size_t *, _offsets);
1097 CkpvAccess(_offsets) = new size_t[32];
1098 CkpvInitialize(PtrQ*,_buffQ);
1099 CkpvInitialize(PtrVec*,_bocInitVec);
1100 CkpvInitialize(void*, _currentChare);
1101 CkpvInitialize(int, _currentChareType);
1102 CkpvInitialize(CkGroupID, _currentGroup);
1103 CkpvInitialize(void *, _currentNodeGroupObj);
1104 CkpvInitialize(CkGroupID, _currentGroupRednMgr);
1105 CkpvInitialize(GroupTable*, _groupTable);
1106 CkpvInitialize(GroupIDTable*, _groupIDTable);
1107 CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
1108 CkpvInitialize(bool, _destroyingNodeGroup);
1109 CkpvAccess(_destroyingNodeGroup) = false;
1110 CkpvInitialize(UInt, _numGroups);
1111 CkpvInitialize(int, _numInitsRecd);
1112 CkpvInitialize(bool, _initdone);
1113 CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
1114 CkpvInitialize(MsgPool*, _msgPool);
1115 CkpvInitialize(CkCoreState *, _coreState);
1117 Added for evacuation-sayantan
1120 CpvInitialize(char *,_validProcessors);
1122 CkpvInitialize(char ,startedEvac);
1123 CpvInitialize(int,serializer);
1125 _initChareTables(); // for checkpointable plain chares
1127 CksvInitialize(UInt, _numNodeGroups);
1128 CksvInitialize(GroupTable*, _nodeGroupTable);
1129 CksvInitialize(GroupIDTable, _nodeGroupIDTable);
1130 CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
1131 CksvInitialize(CmiNodeLock, _nodeLock);
1132 CksvInitialize(PtrVec*,_nodeBocInitVec);
1133 CksvInitialize(UInt,_numInitNodeMsgs);
1134 CkpvInitialize(int,_charmEpoch);
1135 CkpvAccess(_charmEpoch)=0;
1136 CksvInitialize(bool, _triggersSent);
1137 CksvAccess(_triggersSent) = false;
1139 CkpvInitialize(_CkOutStream*, _ckout);
1140 CkpvInitialize(_CkErrStream*, _ckerr);
1141 CkpvInitialize(Stats*, _myStats);
1143 CkpvAccess(_groupIDTable) = new GroupIDTable(0);
1144 CkpvAccess(_groupTable) = new GroupTable;
1145 CkpvAccess(_groupTable)->init();
1146 CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
1147 CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
1148 CkpvAccess(_buffQ) = new PtrQ();
1149 CkpvAccess(_bocInitVec) = new PtrVec();
1151 CkpvAccess(_currentNodeGroupObj) = NULL;
1155 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
1156 CksvAccess(_numInitNodeMsgs) = 0;
1157 CksvAccess(_nodeLock) = CmiCreateLock();
1158 CksvAccess(_nodeGroupTable) = new GroupTable();
1159 CksvAccess(_nodeGroupTable)->init();
1160 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
1161 CksvAccess(_nodeBocInitVec) = new PtrVec();
1166 CmiNodeAllBarrier();
1168 #if ! CMK_BIGSIM_CHARM
1169 initQd(argv); // bigsim calls it in ConverseCommonInit
1172 CkpvAccess(_coreState)=new CkCoreState();
1174 CkpvAccess(_numInitsRecd) = 0;
1175 CkpvAccess(_initdone) = false;
1177 CkpvAccess(_ckout) = new _CkOutStream();
1178 CkpvAccess(_ckerr) = new _CkErrStream();
1180 _charmHandlerIdx = CkRegisterHandler(_bufferHandler);
1181 _initHandlerIdx = CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState));
1182 _roRestartHandlerIdx = CkRegisterHandler(_roRestartHandler);
1183 _exitHandlerIdx = CkRegisterHandler(_exitHandler);
1184 //added for interoperabilitY
1185 _libExitHandlerIdx = CkRegisterHandler(_libExitHandler);
1186 _bocHandlerIdx = CkRegisterHandlerEx(_initHandler, CkpvAccess(_coreState));
1187 #if CMK_SHRINK_EXPAND
1188 // for shrink expand cleanup
1189 _ROGroupRestartHandlerIdx = CkRegisterHandler(_ROGroupRestartHandler);
1195 _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1197 _triggerHandlerIdx = CkRegisterHandler(_triggerHandler);
1200 CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1202 _futuresModuleInit(); // part of futures implementation is a converse module
1203 _loadbalancerInit();
1204 _metabalancerInit();
1205 #if CMK_SMP && CMK_TASKQUEUE
1208 #if CMK_MEM_CHECKPOINT
1209 init_memcheckpt(argv);
1212 initCharmProjections();
1213 #if CMK_TRACE_IN_CHARM
1214 // initialize trace module in ck
1215 traceCharmInit(argv);
1218 CkpvInitialize(int, envelopeEventID);
1219 CkpvAccess(envelopeEventID) = 0;
1220 CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1223 The rank-0 processor of each node calls the
1224 translator-generated "_register" routines.
1226 _register routines call the charm.h "CkRegister*" routines,
1227 which record function pointers and class information for
1228 all Charm entities, like Chares, Arrays, and readonlies.
1230 There's one _register routine generated for each
1231 .ci file. _register routines *must* be called in the
1232 same order on every node, and *must not* be called by
1233 multiple threads simultaniously.
1241 SDAG::registerPUPables();
1242 CmiArgGroup("Charm++",NULL);
1243 _parseCommandLineOpts(argv);
1245 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1246 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1247 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1248 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1249 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1250 CkRegisterChareInCharm(CkIndex_Group::__idx);
1251 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1254 These _register calls are for the built-in
1255 Charm .ci files, like arrays and load balancing.
1256 If you add a .ci file to charm, you'll have to
1257 add a call to the _register routine here, or make
1258 your library into a "-module".
1260 _registerCkFutures();
1262 _registerLBDatabase();
1263 _registerMetaBalancer();
1264 _registerCkCallback();
1267 _registerCkCheckpoint();
1268 _registerCkMulticast();
1269 #if CMK_MEM_CHECKPOINT
1270 _registerCkMemCheckpoint();
1274 CkRegisterMainModule is generated by the (unique)
1275 "mainmodule" .ci file. It will include calls to
1276 register all the .ci files.
1278 CkRegisterMainModule();
1281 _registerExternalModules is actually generated by
1282 charmc at link time (as "moduleinit<pid>.C").
1284 This generated routine calls the _register functions
1285 for the .ci files of libraries linked using "-module".
1286 This funny initialization is most useful for AMPI/FEM
1287 programs, which don't have a .ci file and hence have
1288 no other way to control the _register process.
1290 _registerExternalModules(argv);
1294 /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1295 if (CkMyRank() == 0) {
1296 CpdBreakPointInit();
1298 CmiNodeAllBarrier();
1300 // Execute the initcalls registered in modules
1301 _initCallTable.enumerateInitCalls();
1304 CpdFinishInitialization();
1307 //CmiNodeAllBarrier();
1309 CkpvAccess(_myStats) = new Stats();
1310 CkpvAccess(_msgPool) = new MsgPool();
1312 CmiNodeAllBarrier();
1319 #if CMK_SMP_TRACE_COMMTHREAD
1320 _TRACE_BEGIN_COMPUTATION();
1322 if (!inCommThread) {
1323 _TRACE_BEGIN_COMPUTATION();
1327 #ifdef ADAPT_SCHED_MEM
1329 memCriticalEntries = new int[numMemCriticalEntries];
1331 for(int i=0; i<_entryTable.size(); i++){
1332 if(_entryTable[i]->isMemCritical){
1333 memCriticalEntries[memcnt++] = i;
1339 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1340 _messageLoggingInit();
1347 CpvAccess(_validProcessors) = new char[CkNumPes()];
1348 for(int vProc=0;vProc<CkNumPes();vProc++){
1349 CpvAccess(_validProcessors)[vProc]=1;
1351 _ckEvacBcastIdx = CkRegisterHandler(_ckEvacBcast);
1352 _ckAckEvacIdx = CkRegisterHandler(_ckAckEvac);
1354 CkpvAccess(startedEvac) = 0;
1355 CpvAccess(serializer) = 0;
1358 CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1359 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1360 CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1364 processRaiseEvacFile(_raiseEvacFile);
1367 // CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1368 CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1371 CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1375 if (CkMyRank() == 0) {
1378 CmiNodeAllBarrier();
1380 if (!_replaySystem) {
1381 CkFtFn faultFunc_restart = CkRestartMain;
1382 if (faultFunc == NULL || faultFunc == faultFunc_restart) { // this is not restart from memory
1383 // these two are blocking calls for non-bigsim
1384 #if ! CMK_BIGSIM_CHARM
1385 CmiInitCPUAffinity(argv);
1386 CmiInitMemAffinity(argv);
1389 CmiInitCPUTopology(argv);
1390 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1391 if (CmiCpuTopologyEnabled()) {
1394 CmiGetPesOnPhysicalNode(0, &pelist, &num);
1395 #if !CMK_MULTICORE && !CMK_SMP_NO_COMMTHD
1396 // Count communication threads, if present
1397 // XXX: Assuming uniformity of node size here
1398 num += num/CmiMyNodeSize();
1400 if (!_Cmi_forceSpinOnIdle && num > CmiNumCores())
1403 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());
1404 CmiLock(CksvAccess(_nodeLock));
1405 if (! _Cmi_sleepOnIdle) _Cmi_sleepOnIdle = 1;
1406 CmiUnlock(CksvAccess(_nodeLock));
1413 if (CmiMyRank() == 0) {
1418 if(CmiMyPe() == 0) {
1420 if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name"))
1422 std::stringstream sstm;
1423 sstm << topoFilename << "." << CmiMyPartition();
1424 std::string result = sstm.str();
1426 fp = fopen(result.c_str(), "w");
1428 CkPrintf("Error opening %s file, writing to stdout\n", topoFilename);
1431 TopoManager_printAllocation(fp);
1436 #if CMK_USE_PXSHM && ( CMK_CRAYXE || CMK_CRAYXC ) && CMK_SMP
1437 // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized
1438 // again after cpuaffinity is done
1439 if (CkMyRank() == 0) {
1442 CmiNodeAllBarrier();
1446 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1447 // Register the BG handler for CCS. Notice that this is put into a variable shared by
1448 // the whole real processor. This because converse needs to find it. We check that all
1449 // virtual processors register the same index for this handler.
1455 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1457 if (!inCommThread) {
1458 CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1459 msg->argc = CmiGetArgc(argv);
1461 faultFunc(_restartDir, msg);
1464 }else if(CkMyPe()==0){
1466 _allStats = new Stats*[CkNumPes()];
1468 size_t i, nMains=_mainTable.size();
1470 // Check CkArgMsg and warn if it contains any args starting with '+'.
1471 // These args may be args intended for Charm++ but because of the specific
1472 // build, were not parsed by the RTS.
1474 int argc = CmiGetArgc(argv);
1475 for (int i = 1; i < argc; i++) {
1476 // The +vp option for TCharm is a special case that needs to be checked
1477 // separately, because the number passed does not need a space after
1478 // the vp, and the option can be specified with a '+' or a '-'.
1479 if (strncmp(argv[i],"+vp",3) == 0) {
1480 if (_optSet.count("+vp") == 0) {
1482 CmiPrintf("WARNING: %s is a TCharm command line argument, but you have not compiled with TCharm\n", argv[i]);
1484 } else if (strncmp(argv[i],"-vp",3) == 0) {
1485 CmiPrintf("WARNING: %s is no longer valid because -vp has been deprecated. Please use +vp.\n", argv[i]);
1486 } else if (argv[i][0] == '+' && _optSet.count(argv[i]) == 0) {
1488 CmiPrintf("WARNING: %s is a command line argument beginning with a '+' but was not parsed by the RTS.\n", argv[i]);
1489 } else if (argv[i][0] == '+' && _optSet.count(argv[i]) != 0) {
1490 fprintf(stderr,"%s is used more than once. Please remove duplicate arguments.\n", argv[i]);
1491 CmiAbort("Bad command-line argument\n");
1495 CmiPrintf("If any of the above arguments were intended for the RTS you may need to recompile Charm++ with different options.\n");
1498 for(i=0;i<nMains;i++) /* Create all mainchares */
1500 size_t size = _chareTable[_mainTable[i]->chareIdx]->size;
1501 void *obj = malloc(size);
1503 _mainTable[i]->setObj(obj);
1504 CkpvAccess(_currentChare) = obj;
1505 CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1506 CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1507 msg->argc = CmiGetArgc(argv);
1509 quietMode = 0; // allow printing any mainchare user messages
1510 _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1511 if (quietModeRequested) quietMode = 1;
1512 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1513 CpvAccess(_currentObj) = (Chare *)obj;
1518 _STATS_RECORD_CREATE_CHARE_N(nMains);
1519 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1524 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1526 void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1529 //Pack the message and send it to all other processors
1530 envelope *env = UsrToEnv(roMsg);
1531 env->setSrcPe(CkMyPe());
1532 env->setMsgtype(ROMsgMsg);
1534 CmiSetHandler(env, _initHandlerIdx);
1535 CkPackMessage(&env);
1536 CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1537 CpvAccess(_qd)->create(CkNumPes()-1);
1539 //For processor 0, unpack and re-set the global
1540 CkUnpackMessage(&env);
1541 _processROMsgMsg(env);
1545 //Determine the size of the RODataMessage
1547 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1549 //Allocate and fill out the RODataMessage
1550 envelope *env = _allocEnv(RODataMsg, ps.size());
1551 PUP::toMem pp((char *)EnvToUsr(env));
1552 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1554 env->setCount(++_numInitMsgs);
1555 env->setSrcPe(CkMyPe());
1556 CmiSetHandler(env, _initHandlerIdx);
1557 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1558 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1559 CpvAccess(_qd)->create(CkNumPes()-1);
1563 DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1564 // when I am a communication thread, I don't participate initDone.
1566 CkNumberHandlerEx(_bocHandlerIdx, _processHandler, CkpvAccess(_coreState));
1567 CkNumberHandlerEx(_charmHandlerIdx, _processHandler, CkpvAccess(_coreState));
1568 _processBufferedMsgs();
1572 // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1573 if (CpvAccess(cpdSuspendStartup))
1575 //CmiPrintf("In Parallel Debugging mode .....\n");
1589 // this is needed because on o2k, f90 programs have to have main in
1591 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1594 char **argv = new char*[*argc+2];
1596 for(i=0;i <= *argc;i++) {
1597 if (length[i] < 100) {
1598 _argv[i][length[i]]='\0';
1599 argv[i] = &(_argv[i][0]);
1606 ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1609 // user callable function to register an exit function, this function
1610 // will perform task of collecting of info from all pes to pe0, and call
1611 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1612 // see trace-summary for an example.
1613 void registerExitFn(CkExitFn fn)
1615 #if CMK_SHRINK_EXPAND
1616 CkAbort("registerExitFn is called when shrink-expand is enabled!");
1618 _CkExitFnVec.enq(fn);