00001
00002
00003
00004
00005
00006
00007
00014 #include <stdio.h>
00015 #include <math.h>
00016 #include "converse.h"
00017
00018
00019
00020
00021
00022
00023
00024 void CmiAbort(const char *message)
00025 {
00026 CmiError(message);
00027 exit(1);
00028 }
00029
00030
00031
00032
00033
00034
00035
00036 int _Cmi_mype;
00037 int _Cmi_myrank;
00038 int _Cmi_numpes;
00039 int Cmi_nodesize;
00040 int Cmi_stacksize = 64000;
00041 char **CmiArgv;
00042 CmiStartFn CmiStart;
00043 int CmiUsched;
00044 CthThread *CmiThreads;
00045 void* *CmiQueues;
00046 int *CmiBarred;
00047 int CmiNumBarred=0;
00048
00049 CpvDeclare(void*, CmiLocalQueue);
00050
00051
00052
00053
00054
00055
00056
00057 int CmiAsyncMsgSent(c)
00058 CmiCommHandle c ;
00059 {
00060 return 1;
00061 }
00062
00063 void CmiReleaseCommHandle(c)
00064 CmiCommHandle c ;
00065 {
00066 }
00067
00068
00069
00070 static void CmiNext()
00071 {
00072 CthThread t; int index; int orig;
00073 index = (CmiMyPe()+1) % CmiNumPes();
00074 orig = index;
00075 while (1) {
00076 t = CmiThreads[index];
00077 if ((t)&&(!CmiBarred[index])) break;
00078 index = (index+1) % CmiNumPes();
00079 if (index == orig) exit(0);
00080 }
00081 _Cmi_mype = index;
00082 CthResume(t);
00083 }
00084
00085 void CmiExit()
00086 {
00087 CmiThreads[CmiMyPe()] = 0;
00088 CmiFree(CthSelf());
00089 CmiNext();
00090 }
00091
00092 void *CmiGetNonLocal()
00093 {
00094 CmiThreads[CmiMyPe()] = CthSelf();
00095 CmiNext();
00096 return 0;
00097 }
00098
00099 void CmiNotifyIdle()
00100 {
00101 CmiThreads[CmiMyPe()] = CthSelf();
00102 CmiNext();
00103 }
00104
00105 void CmiNodeBarrier()
00106 {
00107 int i;
00108 CmiNumBarred++;
00109 CmiBarred[CmiMyPe()] = 1;
00110 if (CmiNumBarred == CmiNumPes()) {
00111 for (i=0; i<CmiNumPes(); i++) CmiBarred[i]=0;
00112 CmiNumBarred=0;
00113 }
00114 CmiGetNonLocal();
00115 }
00116
00117 void CmiNodeAllBarrier()
00118 {
00119 int i;
00120 CmiNumBarred++;
00121 CmiBarred[CmiMyPe()] = 1;
00122 if (CmiNumBarred == CmiNumPes()) {
00123 for (i=0; i<CmiNumPes(); i++) CmiBarred[i]=0;
00124 CmiNumBarred=0;
00125 }
00126 CmiGetNonLocal();
00127 }
00128
00129 CmiNodeLock CmiCreateLock()
00130 {
00131 CmiNodeLock lk = (CmiNodeLock)malloc(sizeof(int));
00132 *lk = 0;
00133 return lk;
00134 }
00135
00136 void CmiLock(CmiNodeLock lk)
00137 {
00138 while (*lk) CmiGetNonLocal();
00139 *lk = 1;
00140 }
00141
00142 void CmiUnlock(CmiNodeLock lk)
00143 {
00144 if (*lk==0) {
00145 CmiError("CmiNodeLock not locked, can't unlock.");
00146 exit(1);
00147 }
00148 *lk = 0;
00149 }
00150
00151 int CmiTryLock(CmiNodeLock lk)
00152 {
00153 if (*lk==0) { *lk=1; return 0; }
00154 return -1;
00155 }
00156
00157 void CmiDestroyLock(CmiNodeLock lk)
00158 {
00159 free(lk);
00160 }
00161
00162
00163
00164
00165
00166 void CmiSyncSendFn(destPE, size, msg)
00167 int destPE;
00168 int size;
00169 char * msg;
00170 {
00171 char *buf = (char *)CmiAlloc(size);
00172 memcpy(buf,msg,size);
00173 CdsFifo_Enqueue(CmiQueues[destPE],buf);
00174 CQdCreate(CpvAccess(cQdState), 1);
00175 }
00176
00177 CmiCommHandle CmiAsyncSendFn(destPE, size, msg)
00178 int destPE;
00179 int size;
00180 char * msg;
00181 {
00182 char *buf = (char *)CmiAlloc(size);
00183 memcpy(buf,msg,size);
00184 CdsFifo_Enqueue(CmiQueues[destPE],buf);
00185 CQdCreate(CpvAccess(cQdState), 1);
00186 return 0;
00187 }
00188
00189 void CmiFreeSendFn(destPE, size, msg)
00190 int destPE;
00191 int size;
00192 char * msg;
00193 {
00194 CdsFifo_Enqueue(CmiQueues[destPE], msg);
00195 CQdCreate(CpvAccess(cQdState), 1);
00196 }
00197
00198 void CmiSyncBroadcastFn(size, msg)
00199 int size;
00200 char * msg;
00201 {
00202 int i;
00203 for(i=0; i<CmiNumPes(); i++)
00204 if (i != CmiMyPe()) CmiSyncSendFn(i,size,msg);
00205 }
00206
00207 CmiCommHandle CmiAsyncBroadcastFn(size, msg)
00208 int size;
00209 char * msg;
00210 {
00211 CmiSyncBroadcastFn(size, msg);
00212 return 0;
00213 }
00214
00215 void CmiFreeBroadcastFn(size, msg)
00216 int size;
00217 char * msg;
00218 {
00219 CmiSyncBroadcastFn(size, msg);
00220 CmiFree(msg);
00221 }
00222
00223 void CmiSyncBroadcastAllFn(size, msg)
00224 int size;
00225 char * msg;
00226 {
00227 int i;
00228 for(i=0; i<CmiNumPes(); i++)
00229 CmiSyncSendFn(i,size,msg);
00230 }
00231
00232 CmiCommHandle CmiAsyncBroadcastAllFn(size, msg)
00233 int size;
00234 char * msg;
00235 {
00236 CmiSyncBroadcastAllFn(size,msg);
00237 return 0 ;
00238 }
00239
00240 void CmiFreeBroadcastAllFn(size, msg)
00241 int size;
00242 char * msg;
00243 {
00244 int i;
00245 for(i=0; i<CmiNumPes(); i++)
00246 if (i!=CmiMyPe()) CmiSyncSendFn(i,size,msg);
00247 CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
00248 CQdCreate(CpvAccess(cQdState), 1);
00249 }
00250
00251
00252 int CmiBarrier()
00253 {
00254 return -1;
00255 }
00256
00257 int CmiBarrierZero()
00258 {
00259 return -1;
00260 }
00261
00262
00263
00264 static void CmiParseArgs(argv)
00265 char **argv;
00266 {
00267 CmiGetArgInt(argv,"++stacksize",&Cmi_stacksize);
00268 _Cmi_numpes=1;
00269 CmiGetArgInt(argv,"+p",&_Cmi_numpes);
00270 if (CmiNumPes()<1) {
00271 printf("Error: must specify number of processors to simulate with +pXXX\n",CmiNumPes());
00272 exit(1);
00273 }
00274 }
00275
00276 char **CmiInitPE()
00277 {
00278 int argc; char **argv;
00279 argv = CmiCopyArgs(CmiArgv);
00280 CpvAccess(CmiLocalQueue) = CmiQueues[CmiMyPe()];
00281 CmiTimerInit();
00282 ConverseCommonInit(argv);
00283 CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,CmiNotifyIdle,NULL);
00284 return argv;
00285 }
00286
00287 void CmiCallMain()
00288 {
00289 char **argv;
00290 argv = CmiInitPE();
00291 CmiStart(CmiGetArgc(argv), argv);
00292 if (CmiUsched==0) CsdScheduler(-1);
00293 ConverseExit();
00294 }
00295
00296 void ConverseExit()
00297 {
00298 ConverseCommonExit();
00299 CmiThreads[CmiMyPe()] = 0;
00300 CmiNext();
00301 }
00302
00303 #if CMK_CONDS_USE_SPECIAL_CODE
00304 static int CmiSwitchToPEFn(int newpe)
00305 {
00306 int oldpe = _Cmi_mype;
00307 if (newpe == CcdIGNOREPE) return CcdIGNOREPE;
00308 _Cmi_mype = newpe;
00309 return oldpe;
00310 }
00311 #endif
00312
00313
00314 void ConverseInit(argc,argv,fn,usched,initret)
00315 int argc;
00316 char **argv;
00317 CmiStartFn fn;
00318 int usched, initret;
00319 {
00320 CthThread t; int stacksize, i;
00321
00322 #if CMK_USE_HP_MAIN_FIX
00323 #if FOR_CPLUS
00324 _main(argc,argv);
00325 #endif
00326 #endif
00327
00328 CmiSwitchToPE = CmiSwitchToPEFn;
00329
00330 CmiArgv = CmiCopyArgs(argv);
00331 CmiStart = fn;
00332 CmiUsched = usched;
00333 CmiParseArgs(CmiArgv);
00334 CthInit(CmiArgv);
00335 CpvInitialize(void*, CmiLocalQueue);
00336 CmiThreads = (CthThread *)CmiAlloc(CmiNumPes()*sizeof(CthThread));
00337 CmiBarred = (int *)CmiAlloc(CmiNumPes()*sizeof(int));
00338 CmiQueues = (void**)CmiAlloc(CmiNumPes()*sizeof(void*));
00339
00340 smp_mutex = CmiCreateLock();
00341
00342
00343 for(i=0; i<CmiNumPes(); i++) {
00344 t = (i==0) ? CthSelf() : CthCreate(CmiCallMain, 0, Cmi_stacksize);
00345 CmiThreads[i] = t;
00346 CmiBarred[i] = 0;
00347 CmiQueues[i] = CdsFifo_Create();
00348 }
00349 _Cmi_mype = 0;
00350 argv = CmiInitPE();
00351 if (initret==0) {
00352 fn(CmiGetArgc(argv), argv);
00353 if (usched==0) CsdScheduler(-1);
00354 ConverseExit();
00355 }
00356 }
00357