00001 #include "mpi-interoperate.h"
00002
00003 #if PERFORM_DEBUG
00004 #define DEBUG(a) a
00005 #else
00006 #define DEBUG(a)
00007 #endif
00008
00009 int _libExitHandlerIdx;
00010 static bool _libExitStarted = false;
00011
00012 extern std::atomic<int> ckExitComplete;
00013 extern std::atomic<int> _cleanUp;
00014
00015 #if CMK_CONVERSE_MPI
00016 extern MPI_Comm charmComm;
00017 #else
00018 typedef int MPI_Comm;
00019 #endif
00020
00021 extern void LrtsDrainResources();
00022
00023 extern bool _ringexit;
00024 extern int _ringtoken;
00025 extern void _initCharm(int unused_argc, char **argv);
00026 extern void _sendReadonlies();
00027 void CommunicationServerThread(int sleepTime);
00028 extern int CharmLibInterOperate;
00029 extern int userDrivenMode;
00030
00031 void StartInteropScheduler();
00032 void StopInteropScheduler();
00033
00034 void StartCharmScheduler() {
00035 CmiNodeAllBarrier();
00036 StartInteropScheduler();
00037 }
00038
00039 void StopCharmScheduler() {
00040 StopInteropScheduler();
00041 }
00042
00043
00044 void LibCkExit(void)
00045 {
00046
00047 envelope *env = _allocEnv(StartExitMsg);
00048 env->setSrcPe(CkMyPe());
00049 CmiSetHandler(env, _libExitHandlerIdx);
00050 CmiSyncSendAndFree(0, env->getTotalsize(), (char *)env);
00051 }
00052
00053 void _libExitHandler(envelope *env)
00054 {
00055 DEBUG(printf("[%d] Exit started for %d PE %d nodes\n",CmiMyPe(),CmiNumPes(),CmiNumNodes());)
00056 switch(env->getMsgtype()) {
00057 case StartExitMsg:
00058 DEBUG(printf("[%d] Exit started for %d PE %d nodes\n",CmiMyPe(),CmiNumPes(),CmiNumNodes());)
00059 CkAssert(CkMyPe()==0);
00060 case ExitMsg:
00061 CkAssert(CkMyPe()==0);
00062 if(_libExitStarted) {
00063 DEBUG(printf("[%d] Duplicate Exit started for %d PE %d nodes\n",CmiMyPe(),CmiNumPes(),CmiNumNodes());)
00064 CmiFree(env);
00065 return;
00066 }
00067 _libExitStarted = true;
00068 env->setMsgtype(ReqStatMsg);
00069 env->setSrcPe(CkMyPe());
00070
00071 if (_ringexit){
00072 const int stride = CkNumPes()/_ringtoken;
00073 int pe = 0;
00074 while (pe<CkNumPes()) {
00075 CmiSyncSend(pe, env->getTotalsize(), (char *)env);
00076 pe += stride;
00077 }
00078 CmiFree(env);
00079 }else{
00080 DEBUG(printf("[%d] Broadcast Exit for %d PE %d nodes\n",CmiMyPe(),CmiNumPes(),CmiNumNodes());)
00081 CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env);
00082 }
00083 break;
00084 case ReqStatMsg:
00085 DEBUG(printf("[%d] Receive Exit for %d PE %d nodes\n",CmiMyPe(),CmiNumPes(),CmiNumNodes());)
00086 if (_ringexit) {
00087 int stride = CkNumPes()/_ringtoken;
00088 int pe = CkMyPe()+1;
00089 if (pe < CkNumPes() && pe % stride != 0)
00090 CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env);
00091 else
00092 CmiFree(env);
00093 }
00094 else
00095 CmiFree(env);
00096
00097 DEBUG(printf("[%d/%d] Am done here\n",CmiMyRank(),CmiMyPe());)
00098 #if !CMK_SMP
00099 LrtsDrainResources();
00100 #endif
00101 _libExitStarted = false;
00102 StopCharmScheduler();
00103 break;
00104 default:
00105 CmiAbort("Internal Error(_libExitHandler): Unknown-msg-type. Contact Developers.\n");
00106 }
00107 }
00108
00109
00110
00111
00112 void CharmBeginInit(int argc, char** argv) {
00113 #if !defined CMK_USE_LRTS || !CMK_USE_LRTS
00114 CmiAbort("Interop is not supported in non-LRTS machine layers.");
00115 #endif
00116
00117 userDrivenMode = 1;
00118 CharmLibInterOperate = true;
00119 ConverseInit(argc, argv, (CmiStartFn)_initCharm, 1, 0);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 void CharmFinishInit() {
00129 if (CkMyPe() == 0) {
00130 _sendReadonlies();
00131 }
00132 StartInteropScheduler();
00133 }
00134
00135
00136
00137
00138 void CharmInit(int argc, char** argv) {
00139 CharmBeginInit(argc, argv);
00140 CharmFinishInit();
00141 }
00142
00143
00144
00145
00146
00147 void CharmLibInit(MPI_Comm userComm, int argc, char **argv) {
00148
00149 #if CMK_USE_LRTS && !CMK_HAS_INTEROP
00150 if(!userDrivenMode) {
00151 CmiAbort("mpi-interoperate not supported in this machine layer; did you mean to use CharmInit?");
00152 }
00153 #endif
00154
00155 #if CMK_CONVERSE_MPI
00156 if(!userDrivenMode) {
00157 MPI_Comm_dup(userComm, &charmComm);
00158 }
00159 #endif
00160
00161 CharmLibInterOperate = true;
00162 ConverseInit(argc, argv, (CmiStartFn)_initCharm, 1, 0);
00163 StartInteropScheduler();
00164 }
00165
00166
00167
00168
00169
00170
00171 #undef CkExit
00172 #define CkExit CKEXIT_0 // CKEXIT_0 and other CkExit macros defined in charm.h
00173 void CharmLibExit() {
00174 _cleanUp = 1;
00175 CmiNodeAllBarrier();
00176 if(CkMyPe() == 0) {
00177 CkExit();
00178 }
00179 if (CmiMyRank() == CmiMyNodeSize()) {
00180 while (ckExitComplete.load() == 0) { CommunicationServerThread(5); }
00181 } else {
00182 CsdScheduler(-1);
00183 CmiNodeAllBarrier();
00184 }
00185 }