23ea9d9b6c96f183ed9f5331666ad0b2c4a8c8b0
[charm.git] / src / ck-core / init.C
1 /**
2 \addtogroup CkInit
3 \brief Controls the Charm++ startup process.
4
5 This file runs the entire Charm++ startup process.
6
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.
11
12 The rank 0 processor of each node then does
13 the Charm++ registration, by calling the various _register
14 routines.  
15
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.
24
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.  
29
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.  
34
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.
39
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.
43
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>
60
61 This process should not have race conditions, but it can
62 never be excluded...
63 */
64 /*@{*/
65
66 #include "ck.h"
67 #include "trace.h"
68
69 void CkRestartMain(const char* dirname);
70
71 #define  DEBUGF(x)     //CmiPrintf x;
72
73 #ifdef CALCULATE_HOPS
74 /** Turn on manually if you want to calculate hops from within Charm++
75 for some application **/
76
77 #include "TopoManager.h"
78
79 TopoManager *tmgr = NULL;
80 double hops = 0;
81
82 extern "C" void calculateTotalHops(int pe1, int pe2, int size) {
83   if(tmgr == NULL)
84     tmgr = new TopoManager();
85   hops += (tmgr->getHopsBetweenRanks(pe1, pe2) * size);
86 }
87
88 extern "C" void printTotalHops() {
89   CmiPrintf("TOTAL HOPS %lf\n", hops/(1024*1024) );
90 }
91 #endif
92
93 UChar _defaultQueueing = CK_QUEUEING_FIFO;
94
95 UInt  _printCS = 0;
96 UInt  _printSS = 0;
97
98 /**
99  * This value has the number of total initialization message a processor awaits.
100  * It is received on nodes other than zero together with the ROData message.
101  * Even though it is shared by all processors it is ok: it doesn't matter when and
102  * by who it is set, provided that it becomes equal to the number of awaited messages
103  * (which is always at least one ---the readonly data message).
104  */
105 UInt  _numExpectInitMsgs = 0;
106 /**
107  * This number is used only by processor zero to count how many messages it will
108  * send out for the initialization process. After the readonly data message is sent
109  * (containing this counter), its value becomes irrelevant.
110  */
111 UInt  _numInitMsgs = 0;
112 /**
113  * Count the number of nodegroups that have been created in mainchares.
114  * Since the nodegroup creation is executed by a single processor in a
115  * given node, this value must be seen by all processors in a node.
116  */
117 CksvDeclare(UInt,_numInitNodeMsgs);
118 int   _infoIdx;
119 int   _charmHandlerIdx;
120 int   _initHandlerIdx;
121 int   _roRestartHandlerIdx;
122 int   _bocHandlerIdx;
123 int   _qdHandlerIdx;
124 int   _qdCommHandlerIdx;
125 int   _triggerHandlerIdx;
126 int   _mainDone = 0;
127 CksvDeclare(int, _triggersSent);
128
129 CkOutStream ckout;
130 CkErrStream ckerr;
131 CkInStream  ckin;
132
133 CkpvDeclare(void*,       _currentChare);
134 CkpvDeclare(int,         _currentChareType);
135 CkpvDeclare(CkGroupID,   _currentGroup);
136 CkpvDeclare(void*,       _currentNodeGroupObj);
137 CkpvDeclare(CkGroupID,   _currentGroupRednMgr);
138 CkpvDeclare(GroupTable*, _groupTable);
139 CkpvDeclare(GroupIDTable*, _groupIDTable);
140 CkpvDeclare(CmiImmediateLockType, _groupTableImmLock);
141 CkpvDeclare(UInt, _numGroups);
142
143 CkpvDeclare(CkCoreState *, _coreState);
144
145 CksvDeclare(UInt, _numNodeGroups);
146 CksvDeclare(GroupTable*, _nodeGroupTable);
147 CksvDeclare(GroupIDTable, _nodeGroupIDTable);
148 CksvDeclare(CmiImmediateLockType, _nodeGroupTableImmLock);
149 CksvDeclare(CmiNodeLock, _nodeLock);
150 CksvStaticDeclare(PtrVec*,_nodeBocInitVec);
151 CkpvDeclare(int, _charmEpoch);
152
153 CkpvDeclare(Stats*, _myStats);
154 CkpvDeclare(MsgPool*, _msgPool);
155
156 CkpvDeclare(_CkOutStream*, _ckout);
157 CkpvDeclare(_CkErrStream*, _ckerr);
158
159 CkpvStaticDeclare(int,  _numInitsRecd);
160 CkpvStaticDeclare(PtrQ*, _buffQ);
161 CkpvStaticDeclare(PtrVec*, _bocInitVec);
162
163 //for interoperability
164 extern void _libExitHandler(envelope *env);
165 extern int _libExitHandlerIdx;
166
167 /*
168         FAULT_EVAC
169 */
170 CpvCExtern(char *, _validProcessors);
171 CkpvDeclare(char ,startedEvac);
172
173 int    _exitHandlerIdx;
174
175 #if CMK_WITH_STATS
176 static Stats** _allStats = 0;
177 #endif
178 static int   _numStatsRecd = 0;
179 static int   _exitStarted = 0;
180
181 static InitCallTable _initCallTable;
182
183 #if CMK_WITH_STATS
184 #define _STATS_ON(x) (x) = 1
185 #else
186 #define _STATS_ON(x) \
187           if (CkMyPe()==0) CmiPrintf("stats unavailable in optimized version. ignoring...\n");
188 #endif
189
190 // fault tolerance
191 typedef void (*CkFtFn)(const char *, CkArgMsg *);
192 static CkFtFn  faultFunc = NULL;
193 static char* _restartDir;
194
195 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
196 int teamSize=1;
197 int chkptPeriod=1000;
198 bool fastRecovery = false;
199 int parallelRecovery = 1;
200 extern int BUFFER_TIME; //time spent waiting for buffered messages
201 #endif
202
203 // flag for killing processes 
204 extern int killFlag;
205 // file specifying the processes to be killed
206 extern char *killFile;
207 // function for reading the kill file
208 void readKillFile();
209
210
211 int _defaultObjectQ = 0;            // for obejct queue
212 int _ringexit = 0;                  // for charm exit
213 int _ringtoken = 8;
214
215
216 /*
217         FAULT_EVAC
218
219         flag which marks whether or not to trigger the processor shutdowns
220 */
221 static int _raiseEvac=0;
222 static char *_raiseEvacFile;
223 void processRaiseEvacFile(char *raiseEvacFile);
224
225 extern bool useNodeBlkMapping;
226
227 static inline void _parseCommandLineOpts(char **argv)
228 {
229   if (CmiGetArgFlagDesc(argv,"+cs", "Print extensive statistics at shutdown"))
230       _STATS_ON(_printCS);
231   if (CmiGetArgFlagDesc(argv,"+ss", "Print summary statistics at shutdown"))
232       _STATS_ON(_printSS);
233   if (CmiGetArgFlagDesc(argv,"+fifo", "Default to FIFO queuing"))
234       _defaultQueueing = CK_QUEUEING_FIFO;
235   if (CmiGetArgFlagDesc(argv,"+lifo", "Default to LIFO queuing"))
236       _defaultQueueing = CK_QUEUEING_LIFO;
237   if (CmiGetArgFlagDesc(argv,"+ififo", "Default to integer-prioritized FIFO queuing"))
238       _defaultQueueing = CK_QUEUEING_IFIFO;
239   if (CmiGetArgFlagDesc(argv,"+ilifo", "Default to integer-prioritized LIFO queuing"))
240       _defaultQueueing = CK_QUEUEING_ILIFO;
241   if (CmiGetArgFlagDesc(argv,"+bfifo", "Default to bitvector-prioritized FIFO queuing"))
242       _defaultQueueing = CK_QUEUEING_BFIFO;
243   if (CmiGetArgFlagDesc(argv,"+blifo", "Default to bitvector-prioritized LIFO queuing"))
244       _defaultQueueing = CK_QUEUEING_BLIFO;
245   if (CmiGetArgFlagDesc(argv,"+objq", "Default to use object queue for every obejct"))
246   {
247 #if CMK_OBJECT_QUEUE_AVAILABLE
248       _defaultObjectQ = 1;
249       if (CkMyPe()==0)
250         CmiPrintf("Charm++> Create object queue for every Charm object.\n");
251 #else
252       CmiAbort("Charm++> Object queue not enabled, recompile Charm++ with CMK_OBJECT_QUEUE_AVAILABLE defined to 1.");
253 #endif
254   }
255   if(CmiGetArgString(argv,"+restart",&_restartDir))
256       faultFunc = CkRestartMain;
257 #if __FAULT__
258   if (CmiGetArgIntDesc(argv,"+restartaftercrash",&CpvAccess(_curRestartPhase),"restarting this processor after a crash")){      
259 # if CMK_MEM_CHECKPOINT
260       faultFunc = CkMemRestart;
261 # endif
262 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
263       faultFunc = CkMlogRestart;
264 #endif
265       CmiPrintf("[%d] Restarting after crash \n",CmiMyPe());
266   }
267   // reading the killFile
268   if(CmiGetArgStringDesc(argv,"+killFile", &killFile,"Generates SIGKILL on specified processors")){
269     if(faultFunc == NULL){
270       //do not read the killfile if this is a restarting processor
271       killFlag = 1;
272       if(CmiMyPe() == 0){
273         printf("[%d] killFlag set to 1 for file %s\n",CkMyPe(),killFile);
274       }
275     }
276   }
277 #endif
278
279   // shut down program in ring fashion to allow projections output w/o IO error
280   if (CmiGetArgIntDesc(argv,"+ringexit",&_ringtoken, "Program exits in a ring fashion")) 
281   {
282     _ringexit = 1;
283     if (CkMyPe()==0)
284       CkPrintf("Charm++> Program shutdown in token ring (%d).\n", _ringtoken);
285     if (_ringtoken > CkNumPes())  _ringtoken = CkNumPes();
286   }
287         /*
288                 FAULT_EVAC
289
290                 if the argument +raiseevac is present then cause faults
291         */
292         if(CmiGetArgStringDesc(argv,"+raiseevac", &_raiseEvacFile,"Generates processor evacuation on random processors")){
293                 _raiseEvac = 1;
294         }
295 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
296         if(!CmiGetArgIntDesc(argv,"+teamSize",&teamSize,"Set the team size for message logging")){
297         teamSize = 1;
298     }
299     if(!CmiGetArgIntDesc(argv,"+chkptPeriod",&chkptPeriod,"Set the checkpoint period for the message logging fault tolerance algorithm in seconds")){
300         chkptPeriod = 100;
301     }
302         if(CmiGetArgIntDesc(argv,"+fastRecovery", &parallelRecovery, "Parallel recovery with message logging protocol")){
303         fastRecovery = true;
304     }
305 #endif
306
307 #if defined(_FAULT_MLOG_)
308     if(!CmiGetArgIntDesc(argv,"+mlog_local_buffer",&_maxBufferedMessages,"# of local messages buffered in the message logging protoocl")){
309         _maxBufferedMessages = 2;
310     }
311     if(!CmiGetArgIntDesc(argv,"+mlog_remote_buffer",&_maxBufferedTicketRequests,"# of remote ticket requests buffered in the message logging protoocl")){
312         _maxBufferedTicketRequests = 2;
313     }
314     if(!CmiGetArgIntDesc(argv,"+mlog_buffer_time",&BUFFER_TIME,"# Time spent waiting for messages to be buffered in the message logging protoocl")){
315         BUFFER_TIME = 2;
316     }
317 #endif  
318         /* Anytime migration flag */
319         _isAnytimeMigration = true;
320         if (CmiGetArgFlagDesc(argv,"+noAnytimeMigration","The program does not require support for anytime migration")) {
321           _isAnytimeMigration = false;
322         }
323         
324         _isNotifyChildInRed = true;
325         if (CmiGetArgFlagDesc(argv,"+noNotifyChildInReduction","The program has at least one element per processor for each charm array created")) {
326           _isNotifyChildInRed = false;
327         }
328
329         _isStaticInsertion = false;
330         if (CmiGetArgFlagDesc(argv,"+staticInsertion","Array elements are only inserted at construction")) {
331           _isStaticInsertion = true;
332         }
333
334         useNodeBlkMapping = false;
335         if (CmiGetArgFlagDesc(argv,"+useNodeBlkMapping","Array elements are block-mapped in SMP-node level")) {
336           useNodeBlkMapping = true;
337         }
338
339 #if ! CMK_WITH_CONTROLPOINT
340         // Display a warning if charm++ wasn't compiled with control point support but user is expecting it
341         if( CmiGetArgFlag(argv,"+CPSamplePeriod") || 
342             CmiGetArgFlag(argv,"+CPSamplePeriodMs") || 
343             CmiGetArgFlag(argv,"+CPSchemeRandom") || 
344             CmiGetArgFlag(argv,"+CPExhaustiveSearch") || 
345             CmiGetArgFlag(argv,"+CPAlwaysUseDefaults") || 
346             CmiGetArgFlag(argv,"+CPSimulAnneal") || 
347             CmiGetArgFlag(argv,"+CPCriticalPathPrio") || 
348             CmiGetArgFlag(argv,"+CPBestKnown") || 
349             CmiGetArgFlag(argv,"+CPSteering") || 
350             CmiGetArgFlag(argv,"+CPMemoryAware") || 
351             CmiGetArgFlag(argv,"+CPSimplex") || 
352             CmiGetArgFlag(argv,"+CPDivideConquer") || 
353             CmiGetArgFlag(argv,"+CPLDBPeriod") || 
354             CmiGetArgFlag(argv,"+CPLDBPeriodLinear") || 
355             CmiGetArgFlag(argv,"+CPLDBPeriodQuadratic") || 
356             CmiGetArgFlag(argv,"+CPLDBPeriodOptimal") || 
357             CmiGetArgFlag(argv,"+CPDefaultValues") || 
358             CmiGetArgFlag(argv,"+CPGatherAll") || 
359             CmiGetArgFlag(argv,"+CPGatherMemoryUsage") || 
360             CmiGetArgFlag(argv,"+CPGatherUtilization") || 
361             CmiGetArgFlag(argv,"+CPSaveData") || 
362             CmiGetArgFlag(argv,"+CPNoFilterData") || 
363             CmiGetArgFlag(argv,"+CPLoadData") || 
364             CmiGetArgFlag(argv,"+CPDataFilename")    )
365           {         
366             CkAbort("You specified a control point command line argument, but compiled charm++ without control point support.\n");
367           }
368 #endif
369        
370 }
371
372 static void _bufferHandler(void *msg)
373 {
374   DEBUGF(("[%d] _bufferHandler called.\n", CkMyPe()));
375   CkpvAccess(_buffQ)->enq(msg);
376 }
377
378 static void _discardHandler(envelope *env)
379 {
380 //  MESSAGE_PHASE_CHECK(env);
381
382   DEBUGF(("[%d] _discardHandler called.\n", CkMyPe()));
383 #if CMK_MEM_CHECKPOINT
384   CkPrintf("[%d] _discardHandler called!\n", CkMyPe());
385   if (CkInRestarting()) CpvAccess(_qd)->process();
386 #endif
387   CmiFree(env);
388 }
389
390 #if CMK_WITH_STATS
391 static inline void _printStats(void)
392 {
393   DEBUGF(("[%d] _printStats\n", CkMyPe()));
394   int i;
395   if(_printSS || _printCS) {
396     Stats *total = new Stats();
397     _MEMCHECK(total);
398     for(i=0;i<CkNumPes();i++)
399       total->combine(_allStats[i]);
400     CkPrintf("Charm Kernel Summary Statistics:\n");
401     for(i=0;i<CkNumPes();i++) {
402       CkPrintf("Proc %d: [%d created, %d processed]\n", i,
403                _allStats[i]->getCharesCreated(),
404                _allStats[i]->getCharesProcessed());
405     }
406     CkPrintf("Total Chares: [%d created, %d processed]\n",
407              total->getCharesCreated(), total->getCharesProcessed());
408   }
409   if(_printCS) {
410     CkPrintf("Charm Kernel Detailed Statistics (R=requested P=processed):\n\n");
411
412     CkPrintf("         Create    Mesgs     Create    Mesgs     Create    Mesgs\n");
413     CkPrintf("         Chare     for       Group     for       Nodegroup for\n");
414     CkPrintf("PE   R/P Mesgs     Chares    Mesgs     Groups    Mesgs     Nodegroups\n");
415     CkPrintf("---- --- --------- --------- --------- --------- --------- ----------\n");
416
417     for(i=0;i<CkNumPes();i++) {
418       CkPrintf("%4d  R  %9d %9d %9d %9d %9d %9d\n      P  %9d %9d %9d %9d %9d %9d\n",i,
419                _allStats[i]->getCharesCreated(),
420                _allStats[i]->getForCharesCreated(),
421                _allStats[i]->getGroupsCreated(),
422                _allStats[i]->getGroupMsgsCreated(),
423                _allStats[i]->getNodeGroupsCreated(),
424                _allStats[i]->getNodeGroupMsgsCreated(),
425                _allStats[i]->getCharesProcessed(),
426                _allStats[i]->getForCharesProcessed(),
427                _allStats[i]->getGroupsProcessed(),
428                _allStats[i]->getGroupMsgsProcessed(),
429                _allStats[i]->getNodeGroupsProcessed(),
430                _allStats[i]->getNodeGroupMsgsProcessed());
431     }
432   }
433 }
434 #else
435 static inline void _printStats(void) {}
436 #endif
437
438 static inline void _sendStats(void)
439 {
440   DEBUGF(("[%d] _sendStats\n", CkMyPe()));
441 #if CMK_WITH_STATS
442   envelope *env = UsrToEnv(CkpvAccess(_myStats));
443 #else
444   envelope *env = _allocEnv(StatMsg);
445 #endif
446   env->setSrcPe(CkMyPe());
447   CmiSetHandler(env, _exitHandlerIdx);
448   CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
449 }
450
451 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
452 extern void _messageLoggingExit();
453 #endif
454
455 #if __FAULT__
456 //CpvExtern(int, CldHandlerIndex);
457 //extern "C" void CldHandler(char *);
458 extern int index_skipCldHandler;
459 extern void _skipCldHandler(void *converseMsg);
460
461 void _discard_charm_message()
462 {
463   CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
464 //  CkNumberHandler(CpvAccess(CldHandlerIndex), (CmiHandler)_discardHandler);
465   CkNumberHandler(index_skipCldHandler, (CmiHandler)_discardHandler);
466 }
467
468 void _resume_charm_message()
469 {
470   CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler,
471         CkpvAccess(_coreState));
472 //  CkNumberHandler(CpvAccess(CldHandlerIndex), (CmiHandler)CldHandler);
473   CkNumberHandler(index_skipCldHandler, (CmiHandler)_skipCldHandler);
474 }
475 #endif
476
477 static void _exitHandler(envelope *env)
478 {
479   DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype()));
480   switch(env->getMsgtype()) {
481     case StartExitMsg:
482       CkAssert(CkMyPe()==0);
483       if (!_CkExitFnVec.isEmpty()) {
484         CkExitFn fn = _CkExitFnVec.deq();
485         fn();
486         break;
487       }
488       // else goto next
489     case ExitMsg:
490       CkAssert(CkMyPe()==0);
491       if(_exitStarted) {
492         CmiFree(env);
493         return;
494       }
495       _exitStarted = 1;
496       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
497       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
498       env->setMsgtype(ReqStatMsg);
499       env->setSrcPe(CkMyPe());
500       // if exit in ring, instead of broadcasting, send in ring
501       if (_ringexit){
502         DEBUGF(("[%d] Ring Exit \n",CkMyPe()));
503         const int stride = CkNumPes()/_ringtoken;
504         int pe = 0;
505         while (pe<CkNumPes()) {
506           CmiSyncSend(pe, env->getTotalsize(), (char *)env);
507           pe += stride;
508         }
509         CmiFree(env);
510       }else{
511         CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
512       } 
513       break;
514     case ReqStatMsg:
515 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
516       _messageLoggingExit();
517 #endif
518       DEBUGF(("ReqStatMsg on %d\n", CkMyPe()));
519       CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
520       CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
521       /*FAULT_EVAC*/
522       if(CmiNodeAlive(CkMyPe())){
523          _sendStats();
524       _mainDone = 1; // This is needed because the destructors for
525                      // readonly variables will be called when the program
526                      // exits. If the destructor is called while _mainDone
527                      // is 0, it will assume that the readonly variable was
528                      // declared locally. On all processors other than 0, 
529                      // _mainDone is never set to 1 before the program exits.
530 #if CMK_TRACE_ENABLED
531       if (_ringexit) traceClose();
532 #endif
533     }
534       if (_ringexit) {
535         int stride = CkNumPes()/_ringtoken;
536         int pe = CkMyPe()+1;
537         if (pe < CkNumPes() && pe % stride != 0)
538           CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
539         else
540           CmiFree(env);
541       }
542       else
543         CmiFree(env);
544       //everyone exits here - there may be issues with leftover messages in the queue
545       if(CkMyPe()){
546         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
547         ConverseExit();
548                                 if(CharmLibInterOperate)
549                                         CpvAccess(charmLibExitFlag) = 1;
550       }
551       break;
552     case StatMsg:
553       CkAssert(CkMyPe()==0);
554 #if CMK_WITH_STATS
555       _allStats[env->getSrcPe()] = (Stats*) EnvToUsr(env);
556 #endif
557       _numStatsRecd++;
558       DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), _numStatsRecd));
559                         /*FAULT_EVAC*/
560       if(_numStatsRecd==CkNumValidPes()) {
561         _printStats();
562         DEBUGF(("[%d] Calling converse exit \n",CkMyPe()));
563         ConverseExit();
564                                 if(CharmLibInterOperate)
565                                         CpvAccess(charmLibExitFlag) = 1;
566       }
567       break;
568     default:
569       CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n");
570   }
571 }
572
573 /**
574  * Create all groups in this processor (not called on processor zero).
575  * Notice that only groups created in mainchares are processed here;
576  * groups created later are processed as regular messages.
577  */
578 static inline void _processBufferedBocInits(void)
579 {
580   CkCoreState *ck = CkpvAccess(_coreState);
581   CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler, ck);
582   register int i = 0;
583   PtrVec &inits=*CkpvAccess(_bocInitVec);
584   register int len = inits.size();
585   for(i=1; i<len; i++) {
586     envelope *env = inits[i];
587     if(env==0) CkAbort("_processBufferedBocInits: empty message");
588     if(env->isPacked())
589       CkUnpackMessage(&env);
590     _processBocInitMsg(ck,env);
591   }
592   delete &inits;
593 }
594
595 /**
596  * Create all nodegroups in this node (called only by rank zero, and never on node zero).
597  * Notice that only nodegroups created in mainchares are processed here;
598  * nodegroups created later are processed as regular messages.
599  */
600 static inline void _processBufferedNodeBocInits(void)
601 {
602   CkCoreState *ck = CkpvAccess(_coreState);
603   register int i = 0;
604   PtrVec &inits=*CksvAccess(_nodeBocInitVec);
605   register int len = inits.size();
606   for(i=1; i<len; i++) {
607     envelope *env = inits[i];
608     if(env==0) CkAbort("_processBufferedNodeBocInits: empty message");
609     if(env->isPacked())
610       CkUnpackMessage(&env);
611     _processNodeBocInitMsg(ck,env);
612   }
613   delete &inits;
614 }
615
616 static inline void _processBufferedMsgs(void)
617 {
618   CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler,
619         CkpvAccess(_coreState));
620   envelope *env;
621   while(NULL!=(env=(envelope*)CkpvAccess(_buffQ)->deq())) {
622     if(env->getMsgtype()==NewChareMsg || env->getMsgtype()==NewVChareMsg) {
623       if(env->isForAnyPE())
624         _CldEnqueue(CLD_ANYWHERE, env, _infoIdx);
625       else
626         _processHandler((void *)env, CkpvAccess(_coreState));
627     } else {
628       _processHandler((void *)env, CkpvAccess(_coreState));
629     }
630   }
631 }
632
633 static int _charmLoadEstimator(void)
634 {
635   return CkpvAccess(_buffQ)->length();
636 }
637
638 /**
639  * This function is used to send other processors on the same node a signal so
640  * they can check if their _initDone can be called: the reason for this is that
641  * the check at the end of _initHandler can fail due to a missing message containing
642  * a Nodegroup creation. When that message arrives only one processor will receive
643  * it, and thus if no notification is sent to the other processors in the node, they
644  * will never proceed.
645  */
646 static void _sendTriggers(void)
647 {
648   int i, num, first;
649   CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
650   if (CksvAccess(_triggersSent) == 0)
651   {
652     CksvAccess(_triggersSent)++;
653     num = CmiMyNodeSize();
654     register envelope *env = _allocEnv(RODataMsg); // Notice that the type here is irrelevant
655     env->setSrcPe(CkMyPe());
656     CmiSetHandler(env, _triggerHandlerIdx);
657     first = CmiNodeFirst(CmiMyNode());
658     for (i=0; i < num; i++)
659       if(first+i != CkMyPe())
660         CmiSyncSend(first+i, env->getTotalsize(), (char *)env);
661     CmiFree(env);
662   }
663   CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
664 }
665
666 /**
667  * This function (not a handler) is called once and only once per processor.
668  * It signals the processor that the initialization is done and regular messages
669  * can be processed.
670  *
671  * On processor zero it is called by _initCharm, on all other processors either
672  * by _initHandler or _triggerHandler (cannot be both).
673  * When fault-tolerance is active, it is called by the fault-tolerance scheme itself.
674  */
675 void _initDone(void)
676 {
677   DEBUGF(("[%d] _initDone.\n", CkMyPe()));
678   if (!CksvAccess(_triggersSent)) _sendTriggers();
679   CkNumberHandler(_triggerHandlerIdx, (CmiHandler)_discardHandler);
680   CmiNodeBarrier();
681   if(CkMyRank() == 0) {
682     _processBufferedNodeBocInits();
683   }
684   CmiNodeBarrier(); // wait for all nodegroups to be created
685   _processBufferedBocInits();
686   DEBUGF(("Reached CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
687   CmiNodeBarrier();
688   DEBUGF(("Crossed CmiNodeBarrier(), pe = %d, rank = %d\n", CkMyPe(), CkMyRank()));
689   _processBufferedMsgs();
690   CkpvAccess(_charmEpoch)=1;
691 }
692
693 /**
694  * Converse handler receiving a signal from another processors in the same node.
695  * (On _sendTrigger there is the explanation of why this is necessary)
696  * Simply check if with the NodeGroup processed by another processor we reached
697  * the expected count. Notice that it can only be called before _initDone: after
698  * _initDone, a message destined for this handler will go instead to the _discardHandler.
699  */
700 static void _triggerHandler(envelope *env)
701 {
702   if (_numExpectInitMsgs && CkpvAccess(_numInitsRecd) + CksvAccess(_numInitNodeMsgs) == _numExpectInitMsgs)
703   {
704     DEBUGF(("Calling Init Done from _triggerHandler\n"));
705     _initDone();
706   }
707   CmiFree(env);
708 }
709
710 static inline void _processROMsgMsg(envelope *env)
711 {
712   *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
713 }
714
715 static inline void _processRODataMsg(envelope *env)
716 {
717   //Unpack each readonly:
718   PUP::fromMem pu((char *)EnvToUsr(env));
719   for(size_t i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pu);
720   CmiFree(env);
721 }
722
723 /**
724  * This is similar to the _initHandler, only that the Groups and Nodegroups are
725  * initialized from disk, so only one single message is expected.
726  *
727  * It is unclear how Readonly Messages are treated during restart... (if at all considered)
728  */
729 static void _roRestartHandler(void *msg)
730 {
731   CkAssert(CkMyPe()!=0);
732   register envelope *env = (envelope *) msg;
733   CkpvAccess(_numInitsRecd)++;
734   _numExpectInitMsgs = env->getCount();
735   _processRODataMsg(env);
736 }
737
738 /**
739  * This handler is used only during initialization. It receives messages from
740  * processor zero regarding Readonly Data (in one single message), Readonly Messages,
741  * Groups, and Nodegroups.
742  * The Readonly Data message also contains the total number of messages expected
743  * during the initialization phase.
744  * For Groups and Nodegroups, only messages with epoch=0 (meaning created from within
745  * a mainchare) are buffered for special creation, the other messages are buffered
746  * together with all the other regular messages by _bufferHandler (and will be flushed
747  * after all the initialization messages have been processed).
748  */
749 static void _initHandler(void *msg, CkCoreState *ck)
750 {
751   CkAssert(CkMyPe()!=0);
752   register envelope *env = (envelope *) msg;
753   
754   if (ck->watcher!=NULL) {
755     if (!ck->watcher->processMessage(&env,ck)) return;
756   }
757   
758   switch (env->getMsgtype()) {
759     case BocInitMsg:
760       if (env->getGroupEpoch()==0) {
761         CkpvAccess(_numInitsRecd)++;
762         // _processBocInitMsg already handles QD
763         //CpvAccess(_qd)->process();
764         CkpvAccess(_bocInitVec)->insert(env->getGroupNum().idx, env);
765       } else _bufferHandler(msg);
766       break;
767     case NodeBocInitMsg:
768       if (env->getGroupEpoch()==0) {
769         CmiImmediateLock(CksvAccess(_nodeGroupTableImmLock));
770         CksvAccess(_numInitNodeMsgs)++;
771         CksvAccess(_nodeBocInitVec)->insert(env->getGroupNum().idx, env);
772         CmiImmediateUnlock(CksvAccess(_nodeGroupTableImmLock));
773         CpvAccess(_qd)->process();
774       } else _bufferHandler(msg);
775       break;
776     case ROMsgMsg:
777       CkpvAccess(_numInitsRecd)++;
778       CpvAccess(_qd)->process();
779       if(env->isPacked()) CkUnpackMessage(&env);
780       _processROMsgMsg(env);
781       break;
782     case RODataMsg:
783       CkpvAccess(_numInitsRecd)++;
784       CpvAccess(_qd)->process();
785       _numExpectInitMsgs = env->getCount();
786       _processRODataMsg(env);
787       break;
788     default:
789       CmiAbort("Internal Error: Unknown-msg-type. Contact Developers.\n");
790   }
791         DEBUGF(("[%d,%.6lf] _numExpectInitMsgs %d CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs) %d+%d\n",CmiMyPe(),CmiWallTimer(),_numExpectInitMsgs,CkpvAccess(_numInitsRecd),CksvAccess(_numInitNodeMsgs)));
792   if(_numExpectInitMsgs&&(CkpvAccess(_numInitsRecd)+CksvAccess(_numInitNodeMsgs)==_numExpectInitMsgs)) {
793     _initDone();
794   }
795 }
796
797 #if 0
798 /*****************************************
799  *          no longer needed
800  * ***************************************/
801 extern "C"
802 void _CkExit(void) 
803 {
804   CmiAssert(CkMyPe() == 0);
805   // Shuts down Converse handlers for the upper layers on this processor
806   //
807   CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler);
808   CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler);
809   DEBUGF(("[%d] CkExit - _exitStarted:%d %d\n", CkMyPe(), _exitStarted, _exitHandlerIdx));
810
811   if(CkMyPe()==0) {
812     if(_exitStarted)
813       CsdScheduler(-1);
814     envelope *env = _allocEnv(ReqStatMsg);
815     env->setSrcPe(CkMyPe());
816     CmiSetHandler(env, _exitHandlerIdx);
817                 /*FAULT_EVAC*/
818     CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
819   } else {
820     envelope *env = _allocEnv(ExitMsg);
821     env->setSrcPe(CkMyPe());
822     CmiSetHandler(env, _exitHandlerIdx);
823     CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
824   }
825 #if ! CMK_BIGSIM_THREAD
826   _TRACE_END_EXECUTE();
827   //Wait for stats, which will call ConverseExit when finished:
828   CsdScheduler(-1);
829 #endif
830 }
831 #endif
832
833 CkQ<CkExitFn> _CkExitFnVec;
834
835 // triger exit on PE 0,
836 // which traverses _CkExitFnVec to call every registered user exit functions.
837 // Every user exit functions should end with CkExit() to continue the chain
838 extern "C"
839 void CkExit(void)
840 {
841         /*FAULT_EVAC*/
842   DEBUGF(("[%d] CkExit called \n",CkMyPe()));
843     // always send to PE 0
844   envelope *env = _allocEnv(StartExitMsg);
845   env->setSrcPe(CkMyPe());
846   CmiSetHandler(env, _exitHandlerIdx);
847   CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
848
849 #if ! CMK_BIGSIM_THREAD
850   _TRACE_END_EXECUTE();
851   //Wait for stats, which will call ConverseExit when finished:
852         if(!CharmLibInterOperate)
853   CsdScheduler(-1);
854 #endif
855 }
856
857 /* This is a routine called in case the application is closing due to a signal.
858    Tear down structures that must be cleaned up even when unclean exit happens.
859    It is called by the machine layer whenever some problem occurs (it is thus up
860    to the machine layer to call this function). */
861 extern "C"
862 void EmergencyExit(void) {
863 #ifndef __BIGSIM__
864   /* Delete _coreState to force any CkMessageWatcher to close down. */
865   if (CkpvAccess(_coreState) != NULL) {
866     delete CkpvAccess(_coreState);
867     CkpvAccess(_coreState) = NULL;
868   }
869 #endif
870 }
871
872 static void _nullFn(void *, void *)
873 {
874   CmiAbort("Null-Method Called. Program may have Unregistered Module!!\n");
875 }
876
877 extern void _registerLBDatabase(void);
878 extern void _registerPathHistory(void);
879 #if CMK_WITH_CONTROLPOINT
880 extern void _registerControlPoints(void);
881 #endif
882 extern void _registerTraceControlPoints();
883 extern void _registerExternalModules(char **argv);
884 extern void _ckModuleInit(void);
885 extern void _loadbalancerInit();
886 extern void _initChareTables();
887 #if CMK_MEM_CHECKPOINT
888 extern void init_memcheckpt(char **argv);
889 #endif
890 extern "C" void initCharmProjections();
891 extern "C" void CmiInitCPUTopology(char **argv);
892 extern "C" void CmiInitCPUAffinity(char **argv);
893 extern "C" void CmiInitMemAffinity(char **argv);
894 extern "C" void CmiInitPxshm(char **argv);
895
896 extern void TopoManager_init();
897
898 //extern "C" void CldCallback();
899
900 void _registerInitCall(CkInitCallFn fn, int isNodeCall)
901 {
902   if (isNodeCall) _initCallTable.initNodeCalls.enq(fn);
903   else _initCallTable.initProcCalls.enq(fn);
904 }
905
906 void InitCallTable::enumerateInitCalls()
907 {
908   int i;
909 #ifdef __BIGSIM__
910   if(BgNodeRank()==0)        // called only once on an emulating node
911 #else
912   if(CkMyRank()==0) 
913 #endif
914   {
915     for (i=0; i<initNodeCalls.length(); i++) initNodeCalls[i]();
916   }
917   // initproc may depend on initnode calls.
918   CmiNodeAllBarrier();
919   for (i=0; i<initProcCalls.length(); i++) initProcCalls[i]();
920 }
921
922 CpvCExtern(int, cpdSuspendStartup);
923 extern "C" void CpdFreeze(void);
924
925 extern int _dummy_dq;
926
927 extern "C" void initQd(char **argv)
928 {
929         CpvInitialize(QdState*, _qd);
930         CpvAccess(_qd) = new QdState();
931         if (CmiMyRank() == 0) {
932 #if !defined(CMK_CPV_IS_SMP) && !CMK_SHARED_VARS_UNIPROCESSOR
933         CpvAccessOther(_qd, 1) = new QdState(); // for i/o interrupt
934 #endif
935         }
936         _qdHandlerIdx = CmiRegisterHandler((CmiHandler)_qdHandler);
937         _qdCommHandlerIdx = CmiRegisterHandler((CmiHandler)_qdCommHandler);
938         if (CmiGetArgIntDesc(argv,"+qd",&_dummy_dq, "QD time in seconds")) {
939           if (CmiMyPe()==0)
940             CmiPrintf("Charm++> Fake QD using %d seconds.\n", _dummy_dq);
941         }
942 }
943
944 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
945 void CpdBgInit();
946 #endif
947 void CpdBreakPointInit();
948
949 /**
950   This is the main charm setup routine.  It's called
951   on all processors after Converse initialization.
952   This routine gets passed to Converse from "main.C".
953   
954   The main purpose of this routine is to set up the objects
955   and Ckpv's used during a regular Charm run.  See the comment
956   at the top of the file for overall flow.
957 */
958 void _initCharm(int unused_argc, char **argv)
959
960         int inCommThread = (CmiMyRank() == CmiMyNodeSize());
961
962         DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer()));
963
964         CkpvInitialize(size_t *, _offsets);
965         CkpvAccess(_offsets) = new size_t[32];
966         CkpvInitialize(PtrQ*,_buffQ);
967         CkpvInitialize(PtrVec*,_bocInitVec);
968         CkpvInitialize(void*, _currentChare);
969         CkpvInitialize(int,   _currentChareType);
970         CkpvInitialize(CkGroupID, _currentGroup);
971         CkpvInitialize(void *, _currentNodeGroupObj);
972         CkpvInitialize(CkGroupID, _currentGroupRednMgr);
973         CkpvInitialize(GroupTable*, _groupTable);
974         CkpvInitialize(GroupIDTable*, _groupIDTable);
975         CkpvInitialize(CmiImmediateLockType, _groupTableImmLock);
976         CkpvInitialize(UInt, _numGroups);
977         CkpvInitialize(int, _numInitsRecd);
978         CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv;
979         CkpvInitialize(MsgPool*, _msgPool);
980         CkpvInitialize(CkCoreState *, _coreState);
981         /*
982                 Added for evacuation-sayantan
983         */
984 #ifndef __BIGSIM__
985         CpvInitialize(char *,_validProcessors);
986 #endif
987         CkpvInitialize(char ,startedEvac);
988         CpvInitialize(int,serializer);
989
990         _initChareTables();            // for checkpointable plain chares
991
992         CksvInitialize(UInt, _numNodeGroups);
993         CksvInitialize(GroupTable*, _nodeGroupTable);
994         CksvInitialize(GroupIDTable, _nodeGroupIDTable);
995         CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock);
996         CksvInitialize(CmiNodeLock, _nodeLock);
997         CksvInitialize(PtrVec*,_nodeBocInitVec);
998         CksvInitialize(UInt,_numInitNodeMsgs);
999         CkpvInitialize(int,_charmEpoch);
1000         CkpvAccess(_charmEpoch)=0;
1001         CksvInitialize(int, _triggersSent);
1002         CksvAccess(_triggersSent) = 0;
1003
1004         CkpvInitialize(_CkOutStream*, _ckout);
1005         CkpvInitialize(_CkErrStream*, _ckerr);
1006         CkpvInitialize(Stats*, _myStats);
1007
1008         CkpvAccess(_groupIDTable) = new GroupIDTable(0);
1009         CkpvAccess(_groupTable) = new GroupTable;
1010         CkpvAccess(_groupTable)->init();
1011         CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock();
1012         CkpvAccess(_numGroups) = 1; // make 0 an invalid group number
1013         CkpvAccess(_buffQ) = new PtrQ();
1014         CkpvAccess(_bocInitVec) = new PtrVec();
1015
1016         CkpvAccess(_currentNodeGroupObj) = NULL;
1017
1018         if(CkMyRank()==0)
1019         {
1020                 CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number
1021                 CksvAccess(_numInitNodeMsgs) = 0;
1022                 CksvAccess(_nodeLock) = CmiCreateLock();
1023                 CksvAccess(_nodeGroupTable) = new GroupTable();
1024                 CksvAccess(_nodeGroupTable)->init();
1025                 CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock();
1026                 CksvAccess(_nodeBocInitVec) = new PtrVec();
1027         }
1028
1029         CkCallbackInit();
1030         
1031         CmiNodeAllBarrier();
1032
1033 #if ! CMK_BIGSIM_CHARM
1034         initQd(argv);         // bigsim calls it in ConverseCommonInit
1035 #endif
1036
1037         CkpvAccess(_coreState)=new CkCoreState();
1038
1039         CkpvAccess(_numInitsRecd) = 0;
1040
1041         CkpvAccess(_ckout) = new _CkOutStream();
1042         CkpvAccess(_ckerr) = new _CkErrStream();
1043
1044         _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler);
1045         _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
1046         CkNumberHandlerEx(_initHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
1047         _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler);
1048         _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler);
1049         //added for interoperabilitY
1050         _libExitHandlerIdx = CkRegisterHandler((CmiHandler)_libExitHandler);
1051         _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler);
1052         CkNumberHandlerEx(_bocHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState));
1053
1054 #ifdef __BIGSIM__
1055         if(BgNodeRank()==0) 
1056 #endif
1057         _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn);
1058
1059         _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler);
1060         _ckModuleInit();
1061
1062         CldRegisterEstimator((CldEstimator)_charmLoadEstimator);
1063
1064         _futuresModuleInit(); // part of futures implementation is a converse module
1065         _loadbalancerInit();
1066         
1067 #if CMK_MEM_CHECKPOINT
1068         init_memcheckpt(argv);
1069 #endif
1070
1071         initCharmProjections();
1072 #if CMK_TRACE_IN_CHARM
1073         // initialize trace module in ck
1074         traceCharmInit(argv);
1075 #endif
1076         
1077     CkpvInitialize(int, envelopeEventID);
1078     CkpvAccess(envelopeEventID) = 0;
1079         CkMessageWatcherInit(argv,CkpvAccess(_coreState));
1080         
1081         /**
1082           The rank-0 processor of each node calls the 
1083           translator-generated "_register" routines. 
1084           
1085           _register routines call the charm.h "CkRegister*" routines,
1086           which record function pointers and class information for
1087           all Charm entities, like Chares, Arrays, and readonlies.
1088           
1089           There's one _register routine generated for each
1090           .ci file.  _register routines *must* be called in the 
1091           same order on every node, and *must not* be called by 
1092           multiple threads simultaniously.
1093         */
1094 #ifdef __BIGSIM__
1095         if(BgNodeRank()==0) 
1096 #else
1097         if(CkMyRank()==0)
1098 #endif
1099         {
1100                 CmiArgGroup("Charm++",NULL);
1101                 _parseCommandLineOpts(argv);
1102                 _registerInit();
1103                 CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int));
1104                 CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare));
1105                 CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare);
1106                 CkRegisterChareInCharm(CkIndex_Chare::__idx);
1107                 CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup);
1108                 CkRegisterChareInCharm(CkIndex_Group::__idx);
1109                 CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
1110                 
1111                 /**
1112                   These _register calls are for the built-in
1113                   Charm .ci files, like arrays and load balancing.
1114                   If you add a .ci file to charm, you'll have to 
1115                   add a call to the _register routine here, or make
1116                   your library into a "-module".
1117                 */
1118                 _registerCkFutures();
1119                 _registerCkArray();
1120                 _registerLBDatabase();
1121                 _registerCkCallback();
1122                 _registertempo();
1123                 _registerwaitqd();
1124                 _registercharisma();
1125                 _registerCkCheckpoint();
1126 #if CMK_MEM_CHECKPOINT
1127                 _registerCkMemCheckpoint();
1128 #endif
1129
1130
1131                 /*
1132                   Setup Control Point Automatic Tuning Framework.
1133
1134                   By default it is enabled as a part of charm, 
1135                   however it won't enable its tracing module 
1136                   unless a +CPEnableMeasurements command line argument
1137                   is specified. See trace-common.C for more info
1138
1139                   Thus there should be no noticable overhead to 
1140                   always having the control point framework linked
1141                   in.
1142                   
1143                 */
1144 #if CMK_WITH_CONTROLPOINT
1145                 _registerPathHistory();
1146                 _registerControlPoints();
1147                 _registerTraceControlPoints();
1148 #endif
1149
1150
1151                 /**
1152                   CkRegisterMainModule is generated by the (unique)
1153                   "mainmodule" .ci file.  It will include calls to 
1154                   register all the .ci files.
1155                 */
1156                 CkRegisterMainModule();
1157
1158                 /**
1159                   _registerExternalModules is actually generated by 
1160                   charmc at link time (as "moduleinit<pid>.C").  
1161                   
1162                   This generated routine calls the _register functions
1163                   for the .ci files of libraries linked using "-module".
1164                   This funny initialization is most useful for AMPI/FEM
1165                   programs, which don't have a .ci file and hence have
1166                   no other way to control the _register process.
1167                 */
1168                 _registerExternalModules(argv);
1169                 
1170                 _registerDone();
1171         }
1172         /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */
1173         if (CkMyRank() == 0) {
1174           CpdBreakPointInit();
1175         }
1176         CmiNodeAllBarrier();
1177
1178         // Execute the initcalls registered in modules
1179         _initCallTable.enumerateInitCalls();
1180
1181 #if CMK_CHARMDEBUG
1182         CpdFinishInitialization();
1183 #endif
1184
1185         //CmiNodeAllBarrier();
1186
1187         CkpvAccess(_myStats) = new Stats();
1188         CkpvAccess(_msgPool) = new MsgPool();
1189
1190         CmiNodeAllBarrier();
1191
1192 #if ! CMK_MEM_CHECKPOINT && !_FAULT_MLOG_ && !_FAULT_CAUSAL_
1193         CmiBarrier();
1194         CmiBarrier();
1195         CmiBarrier();
1196 #endif
1197 #if CMK_SMP_TRACE_COMMTHREAD
1198         _TRACE_BEGIN_COMPUTATION();     
1199 #else
1200         if (!inCommThread) {
1201           _TRACE_BEGIN_COMPUTATION();
1202         }
1203 #endif
1204
1205 #ifdef ADAPT_SCHED_MEM
1206     if(CkMyRank()==0){
1207         memCriticalEntries = new int[numMemCriticalEntries];
1208         int memcnt=0;
1209         for(int i=0; i<_entryTable.size(); i++){
1210             if(_entryTable[i]->isMemCritical){
1211                 memCriticalEntries[memcnt++] = i;
1212             }
1213         }
1214     }
1215 #endif
1216
1217 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1218     _messageLoggingInit();
1219 #endif
1220
1221 #ifndef __BIGSIM__
1222         /*
1223                 FAULT_EVAC
1224         */
1225         CpvAccess(_validProcessors) = new char[CkNumPes()];
1226         for(int vProc=0;vProc<CkNumPes();vProc++){
1227                 CpvAccess(_validProcessors)[vProc]=1;
1228         }
1229         _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast);
1230         _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac);
1231 #endif
1232         CkpvAccess(startedEvac) = 0;
1233         CpvAccess(serializer) = 0;
1234
1235         evacuate = 0;
1236         CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0);
1237 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
1238     CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0);
1239 #endif
1240
1241         if(_raiseEvac){
1242                 processRaiseEvacFile(_raiseEvacFile);
1243                 /*
1244                 if(CkMyPe() == 2){
1245                 //      CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0);
1246                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1247                 }
1248                 if(CkMyPe() == 3){
1249                         CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000);
1250                 }*/
1251         }       
1252
1253     TopoManager_init();
1254     CmiNodeAllBarrier();
1255
1256     if (!_replaySystem) {
1257         if (faultFunc == NULL) {         // this is not restart
1258             // these two are blocking calls for non-bigsim
1259 #if ! CMK_BIGSIM_CHARM
1260           CmiInitCPUAffinity(argv);
1261           CmiInitMemAffinity(argv);
1262 #endif
1263         }
1264         CmiInitCPUTopology(argv);
1265 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1266         if (CmiCpuTopologyEnabled()) {
1267             int *pelist;
1268             int num;
1269             CmiGetPesOnPhysicalNode(0, &pelist, &num);
1270             if (CkMyPe()==0 && !_Cmi_noprocforcommthread && num+num/CmiMyNodeSize() > CmiNumCores()) {
1271                 CkPrintf("\nCharm++> Warning: the number of SMP threads is greater than the number of physical cores, use +CmiNoProcForComThread runtime option.\n\n");
1272             }
1273         }
1274 #endif
1275     }
1276
1277     if(CmiMyPe() == 0) {
1278         char *topoFilename;
1279         if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name")) 
1280         {
1281             TopoManager tmgr;
1282             FILE *fp;
1283             fp = fopen(topoFilename, "w");
1284             if (fp == NULL) {
1285               CkPrintf("Error opening topology.Info.txt file, writing to stdout\n");
1286               fp = stdout;
1287             }
1288             tmgr.printAllocation(fp);
1289             fclose(fp);
1290         }
1291     }
1292
1293 #if CMK_USE_PXSHM && CMK_CRAYXE && CMK_SMP
1294       // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized
1295       // again after cpuaffinity is done
1296     if (CkMyRank() == 0) {
1297       CmiInitPxshm(argv);
1298     }
1299     CmiNodeAllBarrier();
1300 #endif
1301
1302     //CldCallback();
1303 #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG
1304       // Register the BG handler for CCS. Notice that this is put into a variable shared by
1305       // the whole real processor. This because converse needs to find it. We check that all
1306       // virtual processors register the same index for this handler.
1307     CpdBgInit();
1308 #endif
1309
1310         if (faultFunc) {
1311 #if CMK_WITH_STATS
1312                 if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()];
1313 #endif
1314                 if (!inCommThread) {
1315                   CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1316                   msg->argc = CmiGetArgc(argv);
1317                   msg->argv = argv;
1318                   faultFunc(_restartDir, msg);
1319                   CkFreeMsg(msg);
1320                 }
1321         }else if(CkMyPe()==0){
1322 #if CMK_WITH_STATS
1323                 _allStats = new Stats*[CkNumPes()];
1324 #endif
1325                 register size_t i, nMains=_mainTable.size();
1326                 for(i=0;i<nMains;i++)  /* Create all mainchares */
1327                 {
1328                         register int size = _chareTable[_mainTable[i]->chareIdx]->size;
1329                         register void *obj = malloc(size);
1330                         _MEMCHECK(obj);
1331                         _mainTable[i]->setObj(obj);
1332                         CkpvAccess(_currentChare) = obj;
1333                         CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx;
1334                         register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0);
1335                         msg->argc = CmiGetArgc(argv);
1336                         msg->argv = argv;
1337                         _entryTable[_mainTable[i]->entryIdx]->call(msg, obj);
1338 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1339             CpvAccess(_currentObj) = (Chare *)obj;
1340 #endif
1341                 }
1342                 _mainDone = 1;
1343
1344                 _STATS_RECORD_CREATE_CHARE_N(nMains);
1345                 _STATS_RECORD_PROCESS_CHARE_N(nMains);
1346
1347
1348
1349
1350                 for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */
1351                 {
1352                         register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg));
1353                         if(roMsg==0)
1354                                 continue;
1355                         //Pack the message and send it to all other processors
1356                         register envelope *env = UsrToEnv(roMsg);
1357                         env->setSrcPe(CkMyPe());
1358                         env->setMsgtype(ROMsgMsg);
1359                         env->setRoIdx(i);
1360                         CmiSetHandler(env, _initHandlerIdx);
1361                         CkPackMessage(&env);
1362                         CmiSyncBroadcast(env->getTotalsize(), (char *)env);
1363                         CpvAccess(_qd)->create(CkNumPes()-1);
1364
1365                         //For processor 0, unpack and re-set the global
1366                         CkUnpackMessage(&env);
1367                         _processROMsgMsg(env);
1368                         _numInitMsgs++;
1369                 }
1370
1371                 //Determine the size of the RODataMessage
1372                 PUP::sizer ps;
1373                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps);
1374
1375                 //Allocate and fill out the RODataMessage
1376                 envelope *env = _allocEnv(RODataMsg, ps.size());
1377                 PUP::toMem pp((char *)EnvToUsr(env));
1378                 for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp);
1379
1380                 env->setCount(++_numInitMsgs);
1381                 env->setSrcPe(CkMyPe());
1382                 CmiSetHandler(env, _initHandlerIdx);
1383                 DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize()));
1384                 CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env);
1385                 CpvAccess(_qd)->create(CkNumPes()-1);
1386                 _initDone();
1387         }
1388
1389         DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread));
1390         // when I am a communication thread, I don't participate initDone.
1391         if (inCommThread) {
1392                 CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler,
1393                                         CkpvAccess(_coreState));
1394                 CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler
1395 ,
1396                                         CkpvAccess(_coreState));
1397         }
1398
1399 #if CMK_CHARMDEBUG
1400         // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread)
1401        if (CpvAccess(cpdSuspendStartup))
1402        { 
1403           //CmiPrintf("In Parallel Debugging mode .....\n");
1404           CpdFreeze();
1405        }
1406 #endif
1407
1408
1409 #if __FAULT__
1410         if(killFlag){                                                  
1411                 readKillFile();                                        
1412         }
1413 #endif
1414
1415 }
1416
1417 // this is needed because on o2k, f90 programs have to have main in
1418 // fortran90.
1419 extern "C" void fmain_(int *argc,char _argv[][80],int length[])
1420 {
1421   int i;
1422   char **argv = new char*[*argc+2];
1423
1424   for(i=0;i <= *argc;i++) {
1425     if (length[i] < 100) {
1426       _argv[i][length[i]]='\0';
1427       argv[i] = &(_argv[i][0]);
1428     } else {
1429       argv[i][0] = '\0';
1430     }
1431   }
1432   argv[*argc+1]=0;
1433
1434   ConverseInit(*argc, argv, (CmiStartFn) _initCharm, 0, 0);
1435 }
1436
1437 // user callable function to register an exit function, this function
1438 // will perform task of collecting of info from all pes to pe0, and call
1439 // CkExit() on pe0 again to recursively traverse the registered exitFn.
1440 // see trace-summary for an example.
1441 void registerExitFn(CkExitFn fn)
1442 {
1443   _CkExitFnVec.enq(fn);
1444 }
1445
1446 /*@}*/