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