00001
00002
00003
00004
00005
00006 #if CMK_C_INLINE
00007 #define INLINE_KEYWORD inline
00008 #else
00009 #define INLINE_KEYWORD
00010 #endif
00011
00012 #if MACHINE_DEBUG_LOG
00013 FILE *debugLog = NULL;
00014 #endif
00015
00016
00017 #define CMI_CMA_MSGTYPE(msg) ((CmiMsgHeaderBasic *)msg)->cmaMsgType
00018
00019
00020 #ifndef CMK_BROADCAST_SPANNING_TREE
00021 #define CMK_BROADCAST_SPANNING_TREE 1
00022 #endif
00023
00024 #ifndef CMK_BROADCAST_HYPERCUBE
00025 #define CMK_BROADCAST_HYPERCUBE 0
00026 #endif
00027
00028 #define BROADCAST_SPANNING_FACTOR 4
00029
00030 #define BROADCAST_SPANNING_INTRA_FACTOR 8
00031
00032
00033
00034
00035
00036
00037 #define CMI_BROADCAST_ROOT(msg) ((CmiMsgHeaderBasic *)msg)->root
00038 #define CMI_SET_BROADCAST_ROOT(msg, root) CMI_BROADCAST_ROOT(msg) = (root);
00039
00049 #ifndef CMK_OFFLOAD_BCAST_PROCESS
00050 #define CMK_OFFLOAD_BCAST_PROCESS 0
00051 #endif
00052
00053 #if CMK_OFFLOAD_BCAST_PROCESS
00054 CsvDeclare(CMIQueue, procBcastQ);
00055 #if CMK_NODE_QUEUE_AVAILABLE
00056 CsvDeclare(CMIQueue, nodeBcastQ);
00057 #endif
00058 #endif
00059
00060 static int _exitcode;
00061
00062 #if CMK_WITH_STATS
00063 static int MSG_STATISTIC = 0;
00064 int msg_histogram[22];
00065 static int _cmi_log2(int size)
00066 {
00067 int ret = 1;
00068 size = size-1;
00069 while( (size=size>>1)>0) ret++;
00070 return ret;
00071 }
00072 #endif
00073
00074 #if CMK_BROADCAST_HYPERCUBE
00075
00076 static int CmiNodesDim;
00077 #endif
00078
00079
00080 #if CMK_SMP_TRACE_COMMTHREAD
00081 double TraceTimerCommon(void);
00082 #endif
00083
00084 static void handleOneBcastMsg(int size, char *msg);
00085 static void processBcastQs(void);
00086
00087
00088
00089
00090
00091 static INLINE_KEYWORD void processProcBcastMsg(int size, char *msg);
00092 static INLINE_KEYWORD void processNodeBcastMsg(int size, char *msg);
00093 static void SendSpanningChildrenProc(int size, char *msg);
00094 static void SendHyperCubeProc(int size, char *msg);
00095 #if CMK_NODE_QUEUE_AVAILABLE
00096 static void SendSpanningChildrenNode(int size, char *msg);
00097 static void SendHyperCubeNode(int size, char *msg);
00098 #endif
00099
00100 static void SendSpanningChildren(int size, char *msg, int rankToAssign, int startNode);
00101 static void SendHyperCube(int size, char *msg, int rankToAssign, int startNode);
00102
00103 #if USE_COMMON_SYNC_BCAST || USE_COMMON_ASYNC_BCAST
00104 #if !CMK_BROADCAST_SPANNING_TREE && !CMK_BROADCAST_HYPERCUBE
00105 #warning "Broadcast function is based on the plain P2P O(P)-message scheme!!!"
00106 #endif
00107 #endif
00108
00109 #include <assert.h>
00110
00111 void CmiSyncBroadcastFn(int size, char *msg);
00112 CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg);
00113 void CmiFreeBroadcastFn(int size, char *msg);
00114
00115 void CmiSyncBroadcastAllFn(int size, char *msg);
00116 CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg);
00117 void CmiFreeBroadcastAllFn(int size, char *msg);
00118
00119 #if CMK_NODE_QUEUE_AVAILABLE
00120 void CmiSyncNodeBroadcastFn(int size, char *msg);
00121 CmiCommHandle CmiAsyncNodeeroadcastFn(int size, char *msg);
00122 void CmiFreeNodeBroadcastFn(int size, char *msg);
00123
00124 void CmiSyncNodeBroadcastAllFn(int size, char *msg);
00125 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg);
00126 void CmiFreeNodeBroadcastAllFn(int size, char *msg);
00127 #endif
00128
00129
00130
00131 #define CMI_DEST_RANK(msg) ((CmiMsgHeaderBasic *)msg)->rank
00132
00133 #ifndef CMK_HAS_SIZE_IN_MSGHDR
00134 #define CMK_HAS_SIZE_IN_MSGHDR 1
00135 #endif
00136 #if CMK_HAS_SIZE_IN_MSGHDR
00137 #define CMI_MSG_SIZE(msg) ((CmiMsgHeaderBasic *)msg)->size
00138 #else
00139 #define CMI_MSG_SIZE(msg) (CmiAbort("Has no msg size in header"))
00140 #endif
00141
00142 #if CMK_NODE_QUEUE_AVAILABLE
00143
00144
00145
00146
00147 #define DGRAM_NODEMESSAGE (0x1FFB)
00148 #endif
00149
00150
00151 PartitionInfo _partitionInfo;
00152 int _Cmi_mype_global;
00153 int _Cmi_numpes_global;
00154 int _Cmi_mynode_global;
00155 int _Cmi_numnodes_global;
00156 static int _writeToStdout = 1;
00157
00158
00159 int _Cmi_myphysnode_numprocesses;
00160 int _Cmi_mynodesize;
00161 int _Cmi_mynode;
00162 int _Cmi_numnodes;
00163 int _Cmi_numpes;
00164 int userDrivenMode;
00165 extern int CharmLibInterOperate;
00166
00167 CpvDeclare(void*, CmiLocalQueue);
00168
00169
00170 #define P2P_SYNC 0x1
00171 #define P2P_ASYNC 0x2
00172 #define BCAST_SYNC 0x4
00173 #define BCAST_ASYNC 0x8
00174 #define OUT_OF_BAND 0x10
00175
00176 enum MACHINE_SMP_MODE {
00177 INVALID_MODE,
00178 #if CMK_BLUEGENEQ
00179 COMM_THREAD_SEND_RECV = 0,
00180 #else
00181 COMM_THREAD_SEND_RECV = 0,
00182 #endif
00183 COMM_THREAD_ONLY_RECV,
00184 COMM_WORK_THREADS_SEND_RECV,
00185 COMM_THREAD_NOT_EXIST
00186 };
00187
00188 static enum MACHINE_SMP_MODE Cmi_smp_mode_setting = COMM_THREAD_SEND_RECV;
00189
00190
00191
00192 #if CMK_OMP
00193
00194
00195
00196 void CmiSuspendedTaskEnqueue(int targetRank, void *data);
00197 void* CmiSuspendedTaskPop();
00198 #endif
00199
00200 #include <atomic>
00201
00202 extern int CharmLibInterOperate;
00203 std::atomic<int> ckExitComplete {0};
00204
00205 #if CMK_SMP
00206 std::atomic<int> commThdExit {0};
00207
00217 #ifndef CMK_SMP_NO_COMMTHD
00218 #define CMK_SMP_NO_COMMTHD CMK_MULTICORE
00219 #endif
00220
00221 #if CMK_SMP_NO_COMMTHD
00222 int Cmi_commthread = 0;
00223 #else
00224 int Cmi_commthread = 1;
00225 #endif
00226
00227 #endif //CMK_SMP
00228
00229
00230 int Cmi_nodestart = -1;
00231 static int Cmi_nodestartGlobal = -1;
00232
00233
00234
00235
00236
00237 #ifndef NETWORK_PROGRESS_PERIOD_DEFAULT
00238 #define NETWORK_PROGRESS_PERIOD_DEFAULT 1000
00239 #endif
00240
00241 CpvDeclare(unsigned , networkProgressCount);
00242 int networkProgressPeriod;
00243
00244 #if CMK_CCS_AVAILABLE
00245 extern int ccsRunning;
00246 #endif
00247
00248
00249 CMK_NORETURN void CmiAbort(const char *message);
00250 static void PerrorExit(const char *msg);
00251
00252
00253 static void handleOneRecvedMsg(int size, char *msg);
00254
00255
00256
00257
00258
00259 static void SendToPeers(int size, char *msg);
00260
00261
00262 void CmiPushPE(int rank, void *msg);
00263
00264 #if CMK_NODE_QUEUE_AVAILABLE
00265 void CmiPushNode(void *msg);
00266 #endif
00267
00268
00269
00270
00271 #ifndef USE_COMMON_SYNC_P2P
00272 #define USE_COMMON_SYNC_P2P 1
00273 #endif
00274 #ifndef USE_COMMON_ASYNC_P2P
00275 #define USE_COMMON_ASYNC_P2P 1
00276 #endif
00277 #ifndef USE_COMMON_SYNC_BCAST
00278 #define USE_COMMON_SYNC_BCAST 1
00279 #endif
00280 #ifndef USE_COMMON_ASYNC_BCAST
00281 #define USE_COMMON_ASYNC_BCAST 1
00282 #endif
00283
00284 static void CmiSendSelf(char *msg);
00285
00286 void CmiSyncSendFn(int destPE, int size, char *msg);
00287 CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg);
00288 void CmiFreeSendFn(int destPE, int size, char *msg);
00289
00290 #if CMK_NODE_QUEUE_AVAILABLE
00291 static void CmiSendNodeSelf(char *msg);
00292
00293 void CmiSyncNodeSendFn(int destNode, int size, char *msg);
00294 CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg);
00295 void CmiFreeNodeSendFn(int destNode, int size, char *msg);
00296
00297 #endif
00298
00299
00300 static char **Cmi_argv;
00301 static char **Cmi_argvcopy;
00302 static CmiStartFn Cmi_startfn;
00303 static int Cmi_usrsched;
00304 void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret);
00305 static void ConverseRunPE(int everReturn);
00306
00307
00308 static void AdvanceCommunication(int whenidle);
00309 static void CommunicationServer(int sleepTime);
00310 void CommunicationServerThread(int sleepTime);
00311
00312
00313 void *CmiGetNonLocal(void);
00314 #if CMK_NODE_QUEUE_AVAILABLE
00315 void *CmiGetNonLocalNodeQ(void);
00316 #endif
00317
00318 static char *CopyMsg(char *msg, int len);
00319
00320
00321
00322 #include "machine-smp.C"
00323
00324
00325 typedef struct {
00326 int sleepMs;
00327 int nIdles;
00328 CmiState cs;
00329 } CmiIdleState;
00330
00331 static CmiIdleState *CmiNotifyGetState(void);
00332
00345 static void CmiNotifyBeginIdle(CmiIdleState *s);
00346 static void CmiNotifyStillIdle(CmiIdleState *s);
00347 void CmiNotifyIdle(void);
00348
00349
00350 CsvDeclare(CmiNodeState, NodeState);
00351
00352 #if !CMK_SMP
00353
00354 static struct CmiStateStruct Cmi_state;
00355 int _Cmi_mype;
00356 int _Cmi_myrank;
00357
00358 void CmiMemLock(void) {}
00359 void CmiMemUnlock(void) {}
00360
00361 #define CmiGetState() (&Cmi_state)
00362 #define CmiGetStateN(n) (&Cmi_state)
00363
00364 void CmiYield(void) {
00365 sleep(0);
00366 }
00367
00368 static void CmiStartThreads(char **argv) {
00369 CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
00370 _Cmi_mype = Cmi_nodestart;
00371 _Cmi_myrank = 0;
00372 _Cmi_mype_global = _Cmi_mynode_global;
00373 }
00374
00375 INLINE_KEYWORD int CmiNodeSpan(void) {
00376 return 1;
00377 }
00378 #else
00379
00380 INLINE_KEYWORD CMIQueue CmiMyRecvQueue(void) {
00381 return CmiGetState()->recv;
00382 }
00383
00384 #if CMK_NODE_QUEUE_AVAILABLE
00385 INLINE_KEYWORD
00386 #if CMK_LOCKLESS_QUEUE
00387 MPMCQueue
00388 #else
00389 CMIQueue
00390 #endif
00391 CmiMyNodeQueue(void) {
00392 return CsvAccess(NodeState).NodeRecv;
00393 }
00394 #endif
00395
00396 int CmiMyPe(void) {
00397 return CmiGetState()->pe;
00398 }
00399 int CmiNodeSpan(void) {
00400 return (CmiMyNodeSize() + 1);
00401 }
00402 int CmiMyPeGlobal(void) {
00403 return CmiGetPeGlobal(CmiGetState()->pe,CmiMyPartition());
00404 }
00405 int CmiMyRank(void) {
00406 return CmiGetState()->rank;
00407 }
00408 int CmiNodeSize(int node) {
00409 return _Cmi_mynodesize;
00410 }
00411 #if !CMK_MULTICORE // these are defined in converse.h
00412 int CmiNodeFirst(int node) {
00413 return node*_Cmi_mynodesize;
00414 }
00415 int CmiNodeOf(int pe) {
00416 return (pe/_Cmi_mynodesize);
00417 }
00418 int CmiRankOf(int pe) {
00419 return pe%_Cmi_mynodesize;
00420 }
00421 #endif // end of !CMK_MULTICORE
00422 #endif // end of CMK_SMP
00423
00424 static int CmiState_hasMessage(void) {
00425 CmiState cs = CmiGetState();
00426 return CmiIdleLock_hasMessage(cs);
00427 }
00428
00429
00430 CmiCommHandle CmiInterSendNetworkFunc(int destPE, int partition, int size, char *msg, int mode);
00431
00432
00433
00434 #include "machine-broadcast.C"
00435 #include "immediate.C"
00436 #include "machine-commthd-util.C"
00437 #if CMK_USE_CMA
00438
00439 int cma_works, cma_reg_msg, cma_min_threshold, cma_max_threshold;
00440 #include "machine-cma.C"
00441 int CmiDoesCMAWork() {
00442 return cma_works;
00443 }
00444 #endif
00445
00446
00447 static void PerrorExit(const char *msg) {
00448 perror(msg);
00449 exit(1);
00450 }
00451
00452
00453
00454 extern "C" void CmiPushImmediateMsg(void *);
00455
00456
00457 void CmiPushPE(int rank,void *msg) {
00458 CmiState cs = CmiGetStateN(rank);
00459 MACHSTATE2(3,"Pushing message into rank %d's queue %p{",rank, cs->recv);
00460 #if CMK_IMMEDIATE_MSG
00461 if (CmiIsImmediate(msg)) {
00462 MACHSTATE1(3, "[%p] Push Immediate Message begin{",CmiGetState());
00463 CMI_DEST_RANK(msg) = rank;
00464 CmiPushImmediateMsg(msg);
00465 MACHSTATE1(3, "[%p] Push Immediate Message end}",CmiGetState());
00466 return;
00467 }
00468 #endif
00469
00470 #if CMK_MACH_SPECIALIZED_QUEUE
00471 LrtsSpecializedQueuePush(rank, msg);
00472 #elif CMK_SMP_MULTIQ
00473 CMIQueuePush(cs->recv[CmiGetState()->myGrpIdx], (char *)msg);
00474 #else
00475 CMIQueuePush(cs->recv,(char*)msg);
00476 #endif
00477
00478 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
00479 if (_Cmi_sleepOnIdle)
00480 #endif
00481 CmiIdleLock_addMessage(&cs->idle);
00482 MACHSTATE1(3,"} Pushing message into rank %d's queue done",rank);
00483 }
00484
00485 #if CMK_OMP
00486 void CmiSuspendedTaskEnqueue(int targetRank, void *msg) {
00487 CMIQueuePush((PCQueue)CpvAccessOther(CmiSuspendedTaskQueue, targetRank), (char *)msg);
00488 }
00489
00490 void* CmiSuspendedTaskPop() {
00491 return CMIQueuePop((CMIQueue)CpvAccess(CmiSuspendedTaskQueue));
00492 }
00493 #endif
00494
00495 #if CMK_NODE_QUEUE_AVAILABLE
00496
00497 void CmiPushNode(void *msg) {
00498 MACHSTATE(3,"Pushing message into NodeRecv queue");
00499 #if CMK_IMMEDIATE_MSG
00500 if (CmiIsImmediate(msg)) {
00501 CMI_DEST_RANK(msg) = 0;
00502 CmiPushImmediateMsg(msg);
00503 return;
00504 }
00505 #endif
00506
00507 #if CMK_MACH_SPECIALIZED_QUEUE
00508 LrtsSpecializedNodeQueuePush((char *)msg);
00509 #elif CMK_LOCKLESS_QUEUE
00510 MPMCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
00511 #else
00512 CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
00513 CMIQueuePush(CsvAccess(NodeState).NodeRecv, (char *)msg);
00514 CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
00515 #endif
00516
00517 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
00518 if (_Cmi_sleepOnIdle)
00519 #endif
00520 {
00521 CmiState cs=CmiGetStateN(0);
00522 CmiIdleLock_addMessage(&cs->idle);
00523 }
00524 }
00525 #endif
00526
00527
00528 static INLINE_KEYWORD void handleOneRecvedMsg(int size, char *msg) {
00529
00530 #if CMK_SMP_TRACE_COMMTHREAD
00531 TRACE_COMM_CREATION(TraceTimerCommon(), msg);
00532 #endif
00533
00534 #if CMK_USE_CMA
00535
00536 if(cma_reg_msg && CMI_CMA_MSGTYPE(msg) == CMK_CMA_MD_MSG) {
00537 handleOneCmaMdMsg(&size, &msg);
00538 } else if(cma_reg_msg && CMI_CMA_MSGTYPE(msg) == CMK_CMA_ACK_MSG) {
00539 handleOneCmaAckMsg(size, msg);
00540 return;
00541 }
00542 #endif
00543
00544 int isBcastMsg = 0;
00545 #if CMK_BROADCAST_SPANNING_TREE || CMK_BROADCAST_HYPERCUBE
00546 isBcastMsg = (CMI_BROADCAST_ROOT(msg)!=0);
00547 #endif
00548
00549 if (isBcastMsg) {
00550 handleOneBcastMsg(size, msg);
00551 return;
00552 }
00553
00554 #if CMK_NODE_QUEUE_AVAILABLE
00555 if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE){
00556 CmiPushNode(msg);
00557 return;
00558 }
00559 #endif
00560 CmiPushPE(CMI_DEST_RANK(msg), msg);
00561
00562 }
00563
00564
00565 static void SendToPeers(int size, char *msg) {
00566
00567
00568
00569 int exceptRank = CMI_DEST_RANK(msg);
00570 int i;
00571 for (i=0; i<exceptRank; i++) {
00572 CmiPushPE(i, CopyMsg(msg, size));
00573 }
00574 for (i=exceptRank+1; i<CmiMyNodeSize(); i++) {
00575 CmiPushPE(i, CopyMsg(msg, size));
00576 }
00577 }
00578
00579
00580
00581 static void CmiSendSelf(char *msg) {
00582 #if CMK_IMMEDIATE_MSG
00583 if (CmiIsImmediate(msg)) {
00584
00585 CmiPushImmediateMsg(msg);
00586 CmiHandleImmediate();
00587 return;
00588 }
00589 #endif
00590 CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
00591 }
00592
00593
00594 #if USE_COMMON_SYNC_P2P
00595 void CmiSyncSendFn(int destPE, int size, char *msg) {
00596 char *dupmsg = CopyMsg(msg, size);
00597 CmiFreeSendFn(destPE, size, dupmsg);
00598 }
00599
00600 void CmiInterSyncSendFn(int destPE, int partition, int size, char *msg) {
00601 char *dupmsg = CopyMsg(msg, size);
00602 CmiInterFreeSendFn(destPE, partition, size, dupmsg);
00603 }
00604
00605 #if CMK_USE_PXSHM
00606 #include "machine-pxshm.C"
00607 #endif
00608 #if CMK_USE_XPMEM
00609 #include "machine-xpmem.C"
00610 #endif
00611
00612 static int refcount = 0;
00613
00614 #if CMK_USE_OOB
00615 CpvExtern(int, _urgentSend);
00616 #endif
00617
00618
00619
00620 INLINE_KEYWORD CmiCommHandle CmiSendNetworkFunc(int destPE, int size, char *msg, int mode) {
00621
00622 CMI_CMA_MSGTYPE(msg) = CMK_REG_NO_CMA_MSG;
00623 return CmiInterSendNetworkFunc(destPE, CmiMyPartition(), size, msg, mode);
00624 }
00625
00626 CmiCommHandle CmiInterSendNetworkFunc(int destPE, int partition, int size, char *msg, int mode)
00627 {
00628 int rank;
00629 int destLocalNode = CmiNodeOf(destPE);
00630 int destNode = CmiGetNodeGlobal(destLocalNode,partition);
00631
00632 #if CMK_USE_CMA
00633 if(cma_reg_msg && partition == CmiMyPartition() && CmiPeOnSamePhysicalNode(CmiMyPe(), destPE)) {
00634 if(CMI_CMA_MSGTYPE(msg) == CMK_REG_NO_CMA_MSG && cma_min_threshold <= size && size <= cma_max_threshold) {
00635 CmiSendMessageCma(&msg, &size);
00636 }
00637 }
00638 #endif
00639
00640 #if CMK_USE_PXSHM
00641 if ((partition == CmiMyPartition()) && CmiValidPxshm(destLocalNode, size)) {
00642 CmiSendMessagePxshm(msg, size, destLocalNode, &refcount);
00643
00644 return 0;
00645 }
00646 #endif
00647 #if CMK_USE_XPMEM
00648 if ((partition == CmiMyPartition()) && CmiValidXpmem(destLocalNode, size)) {
00649 CmiSendMessageXpmem(msg, size, destLocalNode, &refcount);
00650
00651 return 0;
00652 }
00653 #endif
00654 #if CMK_PERSISTENT_COMM
00655 if (CpvAccess(phs)) {
00656 if (size > PERSIST_MIN_SIZE) {
00657 CmiAssert(CpvAccess(curphs) < CpvAccess(phsSize));
00658 PersistentSendsTable *slot = (PersistentSendsTable *)CpvAccess(phs)[CpvAccess(curphs)];
00659 CmiAssert(CmiNodeOf(slot->destPE) == destLocalNode);
00660 LrtsSendPersistentMsg(CpvAccess(phs)[CpvAccess(curphs)], destNode, size, msg);
00661 return 0;
00662 }
00663 }
00664 #endif
00665
00666 #if CMK_WITH_STATS
00667 if (MSG_STATISTIC)
00668 {
00669 int ret_log = _cmi_log2(size);
00670 if(ret_log >21) ret_log = 21;
00671 msg_histogram[ret_log]++;
00672 }
00673 #endif
00674 #if CMK_USE_OOB
00675 if (CpvAccess(_urgentSend)) mode |= OUT_OF_BAND;
00676 #endif
00677 return LrtsSendFunc(destNode, CmiGetPeGlobal(destPE,partition), size, msg, mode);
00678 }
00679
00680
00681
00682 void CmiFreeSendFn(int destPE, int size, char *msg) {
00683 CmiInterFreeSendFn(destPE, CmiMyPartition(), size, msg);
00684 }
00685
00686
00687 void CmiInterFreeSendFn(int destPE, int partition, int size, char *msg) {
00688 CMI_SET_BROADCAST_ROOT(msg, 0);
00689
00690
00691 CMI_CMA_MSGTYPE(msg) = CMK_REG_NO_CMA_MSG;
00692 #if CMI_QD
00693 CQdCreate(CpvAccess(cQdState), 1);
00694 #endif
00695 if (CmiMyPe()==destPE && partition == CmiMyPartition()) {
00696 CmiSendSelf(msg);
00697 #if CMK_PERSISTENT_COMM
00698 if (CpvAccess(phs)) CpvAccess(curphs)++;
00699 #endif
00700 }
00701 else {
00702 int destNode = CmiNodeOf(destPE);
00703 int destRank = CmiRankOf(destPE);
00704 #if CMK_SMP
00705 if (CmiMyNode()==destNode && partition == CmiMyPartition()) {
00706 CmiPushPE(destRank, msg);
00707 #if CMK_PERSISTENT_COMM
00708 if (CpvAccess(phs)) CpvAccess(curphs)++;
00709 #endif
00710 return;
00711 }
00712 #endif
00713 CMI_DEST_RANK(msg) = destRank;
00714 CmiInterSendNetworkFunc(destPE, partition, size, msg, P2P_SYNC);
00715
00716 #if CMK_PERSISTENT_COMM
00717 if (CpvAccess(phs)) CpvAccess(curphs)++;
00718 #endif
00719 }
00720 }
00721 #endif
00722
00723 #if USE_COMMON_ASYNC_P2P
00724
00725 CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg) {
00726 int destNode = CmiNodeOf(destPE);
00727 if (destNode == CmiMyNode()) {
00728 CmiSyncSendFn(destPE,size,msg);
00729 return 0;
00730 } else {
00731 #if CMK_WITH_STATS
00732 if ( MSG_STATISTIC)
00733 {
00734 int ret_log = _cmi_log2(size);
00735 if(ret_log >21) ret_log = 21;
00736 msg_histogram[ret_log]++;
00737 }
00738 #endif
00739 return CmiSendNetworkFunc(destPE, size, msg, P2P_ASYNC);
00740 }
00741 }
00742 #endif
00743
00744 #if CMK_NODE_QUEUE_AVAILABLE
00745 static void CmiSendNodeSelf(char *msg) {
00746 #if CMK_IMMEDIATE_MSG
00747 if (CmiIsImmediate(msg)) {
00748 CmiPushImmediateMsg(msg);
00749 if (!_immRunning) CmiHandleImmediate();
00750 return;
00751 }
00752 #endif
00753 #if CMK_MACH_SPECIALIZED_QUEUE
00754 LrtsSpecializedNodeQueuePush(msg);
00755 #elif CMK_LOCKLESS_QUEUE
00756 MPMCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
00757 #else
00758 CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
00759 CMIQueuePush(CsvAccess(NodeState).NodeRecv, msg);
00760 CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
00761 #endif
00762 }
00763
00764
00765 #if USE_COMMON_SYNC_P2P
00766 void CmiSyncNodeSendFn(int destNode, int size, char *msg) {
00767 char *dupmsg = CopyMsg(msg, size);
00768 CmiFreeNodeSendFn(destNode, size, dupmsg);
00769 }
00770
00771 void CmiInterSyncNodeSendFn(int destNode, int partition, int size, char *msg) {
00772 char *dupmsg = CopyMsg(msg, size);
00773 CmiInterFreeNodeSendFn(destNode, partition, size, dupmsg);
00774 }
00775
00776
00777 void CmiFreeNodeSendFn(int destNode, int size, char *msg) {
00778 CmiInterFreeNodeSendFn(destNode, CmiMyPartition(), size, msg);
00779 }
00780
00781 void CmiInterFreeNodeSendFn(int destNode, int partition, int size, char *msg) {
00782 CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
00783 #if CMI_QD
00784 CQdCreate(CpvAccess(cQdState), 1);
00785 #endif
00786 CMI_SET_BROADCAST_ROOT(msg, 0);
00787
00788 CMI_CMA_MSGTYPE(msg) = CMK_REG_NO_CMA_MSG;
00789 if (destNode == CmiMyNode() && CmiMyPartition() == partition) {
00790 CmiSendNodeSelf(msg);
00791 } else {
00792 #if CMK_WITH_STATS
00793 if ( MSG_STATISTIC)
00794 {
00795 int ret_log = _cmi_log2(size);
00796 if(ret_log >21) ret_log = 21;
00797 msg_histogram[ret_log]++;
00798 }
00799 #endif
00800 CmiInterSendNetworkFunc(CmiNodeFirst(destNode), partition, size, msg, P2P_SYNC);
00801 }
00802 #if CMK_PERSISTENT_COMM
00803 if (CpvAccess(phs)) CpvAccess(curphs)++;
00804 #endif
00805 }
00806 #endif
00807
00808 #if USE_COMMON_ASYNC_P2P
00809
00810 CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg) {
00811 if (destNode == CmiMyNode()) {
00812 CmiSyncNodeSendFn(destNode, size, msg);
00813 return 0;
00814 } else {
00815 #if CMK_WITH_STATS
00816 if ( MSG_STATISTIC)
00817 {
00818 int ret_log = _cmi_log2(size);
00819 if(ret_log >21) ret_log = 21;
00820 msg_histogram[ret_log]++;
00821 }
00822 #endif
00823 return CmiSendNetworkFunc(CmiNodeFirst(destNode), size, msg, P2P_ASYNC);
00824 }
00825 }
00826 #endif
00827 #endif
00828
00829
00830 #if defined(_WIN32)
00831
00832 #define strtok_r(x,y,z) strtok(x,y)
00833 #endif
00834
00835 #include "TopoManager.h"
00836 extern "C" void createCustomPartitions(int numparts, int *partitionSize, int *nodeMap);
00837 extern "C" void setDefaultPartitionParams(void);
00838
00839 void create_topoaware_partitions(void) {
00840 int i, j, numparts_bak;
00841 Partition_Type type_bak;
00842 int *testMap;
00843
00844 _partitionInfo.nodeMap = (int*)malloc(CmiNumNodesGlobal()*sizeof(int));
00845 _MEMCHECK(_partitionInfo.nodeMap);
00846
00847 type_bak = _partitionInfo.type;
00848 _partitionInfo.type = PARTITION_SINGLETON;
00849
00850 numparts_bak = _partitionInfo.numPartitions;
00851 _partitionInfo.numPartitions = 1;
00852
00853 _partitionInfo.myPartition = 0;
00854
00855 _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
00856
00857 TopoManager_init();
00858 if(_partitionInfo.scheme == 100) {
00859 createCustomPartitions(numparts_bak, _partitionInfo.partitionSize, _partitionInfo.nodeMap);
00860 } else {
00861 TopoManager_createPartitions(_partitionInfo.scheme, numparts_bak, _partitionInfo.nodeMap);
00862 }
00863 TopoManager_free();
00864
00865 _partitionInfo.type = type_bak;
00866 _partitionInfo.numPartitions = numparts_bak;
00867
00868 #if CMK_ERROR_CHECKING
00869 testMap = (int*)calloc(CmiNumNodesGlobal(), sizeof(int));
00870 for(i = 0; i < CmiNumNodesGlobal(); i++) {
00871 assert(_partitionInfo.nodeMap[i] >= 0);
00872 assert(_partitionInfo.nodeMap[i] < CmiNumNodesGlobal());
00873 assert(testMap[_partitionInfo.nodeMap[i]] == 0);
00874 testMap[_partitionInfo.nodeMap[i]] = 1;
00875 }
00876 free(testMap);
00877 #endif
00878
00879 for(i = 0; i < _partitionInfo.numPartitions; i++) {
00880 int endnode = _partitionInfo.partitionPrefix[i] + _partitionInfo.partitionSize[i];
00881 for(j = _partitionInfo.partitionPrefix[i]; j < endnode; j++) {
00882 if(_partitionInfo.nodeMap[j] == CmiMyNodeGlobal()) {
00883 _Cmi_mynode = j - _partitionInfo.partitionPrefix[i];
00884 _partitionInfo.myPartition = i;
00885 }
00886 }
00887 }
00888 }
00889
00890 void CmiSetNumPartitions(int nump) {
00891 _partitionInfo.numPartitions = nump;
00892 }
00893
00894 void CmiSetMasterPartition(void) {
00895 if(!CmiMyNodeGlobal() && _partitionInfo.type != PARTITION_DEFAULT) {
00896 CmiAbort("setMasterPartition used with incompatible option\n");
00897 }
00898 _partitionInfo.type = PARTITION_MASTER;
00899 }
00900
00901 void CmiSetPartitionSizes(char *sizes) {
00902 int length = strlen(sizes);
00903 _partitionInfo.partsizes = (char*)malloc((length+1)*sizeof(char));
00904
00905 if(!CmiMyNodeGlobal() && _partitionInfo.type != PARTITION_DEFAULT) {
00906 CmiAbort("setPartitionSizes used with incompatible option\n");
00907 }
00908
00909 memcpy(_partitionInfo.partsizes, sizes, length*sizeof(char));
00910 _partitionInfo.partsizes[length] = '\0';
00911 _partitionInfo.type = PARTITION_PREFIX;
00912 }
00913
00914 void CmiSetPartitionScheme(int scheme) {
00915 _partitionInfo.scheme = scheme;
00916 _partitionInfo.isTopoaware = 1;
00917 }
00918
00919 void CmiSetCustomPartitioning(void) {
00920 _partitionInfo.scheme = 100;
00921 _partitionInfo.isTopoaware = 1;
00922 }
00923
00924 static void create_partition_map( char **argv)
00925 {
00926 char* token, *tptr;
00927 int i, flag;
00928
00929 _partitionInfo.numPartitions = 1;
00930 _partitionInfo.type = PARTITION_DEFAULT;
00931 _partitionInfo.partsizes = NULL;
00932 _partitionInfo.scheme = 0;
00933 _partitionInfo.isTopoaware = 0;
00934
00935 setDefaultPartitionParams();
00936
00937 if(!CmiGetArgIntDesc(argv,"+partitions", &_partitionInfo.numPartitions,"number of partitions")) {
00938 CmiGetArgIntDesc(argv,"+replicas", &_partitionInfo.numPartitions,"number of partitions");
00939 }
00940
00941 #if CMK_MULTICORE
00942 if(_partitionInfo.numPartitions != 1) {
00943 CmiAbort("+partitions other than 1 is not allowed for multicore build\n");
00944 }
00945 #endif
00946
00947 _partitionInfo.partitionSize = (int*)calloc(_partitionInfo.numPartitions,sizeof(int));
00948 _partitionInfo.partitionPrefix = (int*)calloc(_partitionInfo.numPartitions,sizeof(int));
00949
00950 if (CmiGetArgFlagDesc(argv,"+master_partition","assign a process as master partition")) {
00951 _partitionInfo.type = PARTITION_MASTER;
00952 }
00953
00954 if (CmiGetArgStringDesc(argv, "+partition_sizes", &_partitionInfo.partsizes, "size of partitions")) {
00955 if(!CmiMyNodeGlobal() && _partitionInfo.type != PARTITION_DEFAULT) {
00956 CmiAbort("+partition_sizes used with incompatible option, possibly +master_partition\n");
00957 }
00958 _partitionInfo.type = PARTITION_PREFIX;
00959 }
00960
00961 if (CmiGetArgFlagDesc(argv,"+partition_topology","topology aware partitions")) {
00962 _partitionInfo.isTopoaware = 1;
00963 _partitionInfo.scheme = 1;
00964 }
00965
00966 if (CmiGetArgIntDesc(argv,"+partition_topology_scheme", &_partitionInfo.scheme, "topology aware partitioning scheme")) {
00967 _partitionInfo.isTopoaware = 1;
00968 }
00969
00970 if (CmiGetArgFlagDesc(argv,"+use_custom_partition", "custom partitioning scheme")) {
00971 _partitionInfo.scheme = 100;
00972 _partitionInfo.isTopoaware = 1;
00973 }
00974
00975 if(_partitionInfo.type == PARTITION_DEFAULT) {
00976 if((_Cmi_numnodes_global % _partitionInfo.numPartitions) != 0) {
00977 CmiAbort("Number of partitions does not evenly divide number of processes. Aborting\n");
00978 }
00979 _partitionInfo.partitionPrefix[0] = 0;
00980 _partitionInfo.partitionSize[0] = _Cmi_numnodes_global / _partitionInfo.numPartitions;
00981 for(i = 1; i < _partitionInfo.numPartitions; i++) {
00982 _partitionInfo.partitionSize[i] = _partitionInfo.partitionSize[i-1];
00983 _partitionInfo.partitionPrefix[i] = _partitionInfo.partitionPrefix[i-1] + _partitionInfo.partitionSize[i-1];
00984 }
00985 _partitionInfo.myPartition = _Cmi_mynode_global / _partitionInfo.partitionSize[0];
00986 } else if(_partitionInfo.type == PARTITION_MASTER) {
00987 if(((_Cmi_numnodes_global-1) % (_partitionInfo.numPartitions-1)) != 0) {
00988 CmiAbort("Number of non-master partitions does not evenly divide number of processes minus one. Aborting\n");
00989 }
00990 _partitionInfo.partitionSize[0] = 1;
00991 _partitionInfo.partitionPrefix[0] = 0;
00992 _partitionInfo.partitionSize[1] = (_Cmi_numnodes_global-1) / (_partitionInfo.numPartitions-1);
00993 _partitionInfo.partitionPrefix[1] = 1;
00994 for(i = 2; i < _partitionInfo.numPartitions; i++) {
00995 _partitionInfo.partitionSize[i] = _partitionInfo.partitionSize[i-1];
00996 _partitionInfo.partitionPrefix[i] = _partitionInfo.partitionPrefix[i-1] + _partitionInfo.partitionSize[i-1];
00997 }
00998 _partitionInfo.myPartition = 1 + (_Cmi_mynode_global-1) / _partitionInfo.partitionSize[1];
00999 if(!_Cmi_mynode_global)
01000 _partitionInfo.myPartition = 0;
01001 } else if(_partitionInfo.type == PARTITION_PREFIX) {
01002 token = strtok_r(_partitionInfo.partsizes, ",", &tptr);
01003 while (token)
01004 {
01005 int i,j;
01006 int hasdash=0, hascolon=0, hasdot=0;
01007 int start, end, stride = 1, block = 1, size;
01008 for (i = 0; i < strlen(token); i++) {
01009 if (token[i] == '-') hasdash=1;
01010 else if (token[i] == ':') hascolon=1;
01011 else if (token[i] == '.') hasdot=1;
01012 }
01013 if (hasdash) {
01014 if (hascolon) {
01015 if (hasdot) {
01016 if (sscanf(token, "%d-%d:%d.%d#%d", &start, &end, &stride, &block, &size) != 5)
01017 printf("Warning: Check the format of \"%s\".\n", token);
01018 }
01019 else {
01020 if (sscanf(token, "%d-%d:%d#%d", &start, &end, &stride, &size) != 4)
01021 printf("Warning: Check the format of \"%s\".\n", token);
01022 }
01023 }
01024 else {
01025 if (sscanf(token, "%d-%d#%d", &start, &end, &size) != 3)
01026 printf("Warning: Check the format of \"%s\".\n", token);
01027 }
01028 }
01029 else {
01030 if (sscanf(token, "%d#%d", &start, &size) != 2) {
01031 printf("Warning: Check the format of \"%s\".\n", token);
01032 }
01033 end = start;
01034 }
01035 if (block > stride) {
01036 printf("Warning: invalid block size in \"%s\" ignored.\n", token);
01037 block = 1;
01038 }
01039 for (i = start; i <= end; i += stride) {
01040 for (j = 0; j < block; j++) {
01041 if (i + j > end) break;
01042 _partitionInfo.partitionSize[i+j] = size;
01043 }
01044 }
01045 token = strtok_r(NULL, ",", &tptr);
01046 }
01047 _partitionInfo.partitionPrefix[0] = 0;
01048 _partitionInfo.myPartition = 0;
01049 for(i = 1; i < _partitionInfo.numPartitions; i++) {
01050 if(_partitionInfo.partitionSize[i-1] <= 0) {
01051 CmiAbort("Partition size has to be greater than zero.\n");
01052 }
01053 _partitionInfo.partitionPrefix[i] = _partitionInfo.partitionPrefix[i-1] + _partitionInfo.partitionSize[i-1];
01054 if((_Cmi_mynode_global >= _partitionInfo.partitionPrefix[i]) && (_Cmi_mynode_global < (_partitionInfo.partitionPrefix[i] + _partitionInfo.partitionSize[i]))) {
01055 _partitionInfo.myPartition = i;
01056 }
01057 }
01058 if(_partitionInfo.partitionSize[i-1] <= 0) {
01059 CmiAbort("Partition size has to be greater than zero.\n");
01060 }
01061 }
01062 _Cmi_mynode = _Cmi_mynode - _partitionInfo.partitionPrefix[_partitionInfo.myPartition];
01063
01064 if(_partitionInfo.isTopoaware) {
01065 create_topoaware_partitions();
01066 }
01067 }
01068
01069 void CmiCreatePartitions(char **argv) {
01070 _Cmi_numnodes_global = _Cmi_numnodes;
01071 _Cmi_mynode_global = _Cmi_mynode;
01072 _Cmi_numpes_global = _Cmi_numnodes_global * _Cmi_mynodesize;
01073
01074 if(Cmi_nodestart != -1) {
01075 Cmi_nodestartGlobal = Cmi_nodestart;
01076 } else {
01077 Cmi_nodestartGlobal = _Cmi_mynode_global * _Cmi_mynodesize;
01078 }
01079
01080
01081 if(_partitionInfo.numPartitions > _Cmi_numnodes_global) {
01082 CmiAbort("Number of partitions requested is greater than the number of nodes\n");
01083 }
01084 create_partition_map(argv);
01085
01086
01087 _Cmi_numnodes = CmiMyPartitionSize();
01088
01089 }
01090
01091 int node_lToGTranslate(int node, int partition) {
01092 int rank;
01093 if(_partitionInfo.type == PARTITION_SINGLETON) {
01094 return node;
01095 } else if(_partitionInfo.type == PARTITION_DEFAULT) {
01096 rank = (partition * _partitionInfo.partitionSize[0]) + node;
01097 } else if(_partitionInfo.type == PARTITION_MASTER) {
01098 if(partition == 0) {
01099 CmiAssert(node == 0);
01100 rank = 0;
01101 } else {
01102 rank = 1 + ((partition - 1) * _partitionInfo.partitionSize[1]) + node;
01103 }
01104 } else if(_partitionInfo.type == PARTITION_PREFIX) {
01105 rank = _partitionInfo.partitionPrefix[partition] + node;
01106 } else {
01107 CmiAbort("Partition type did not match any of the supported types\n");
01108 }
01109 if(_partitionInfo.isTopoaware) {
01110 return _partitionInfo.nodeMap[rank];
01111 } else {
01112 return rank;
01113 }
01114 }
01115
01116 int pe_lToGTranslate(int pe, int partition) {
01117 if(_partitionInfo.type == PARTITION_SINGLETON)
01118 return pe;
01119
01120 if(pe < CmiPartitionSize(partition)*CmiMyNodeSize()) {
01121 return node_lToGTranslate(CmiNodeOf(pe),partition)*CmiMyNodeSize() + CmiRankOf(pe);
01122 }
01123
01124 return CmiNumPesGlobal() + node_lToGTranslate(pe - CmiPartitionSize(partition)*CmiMyNodeSize(), partition);
01125 }
01126
01127 INLINE_KEYWORD int node_gToLTranslate(int node) {
01128 CmiAbort("Conversion from global rank to local rank is not supported. Please contact Charm++ developers with the use case.\n");
01129 return -1;
01130 }
01131
01132 INLINE_KEYWORD int pe_gToLTranslate(int pe) {
01133 CmiAbort("Conversion from global rank to local rank is not supported. Please contact Charm++ developers with the use case.\n");
01134 return -1;
01135 }
01136
01137
01138 extern int quietMode;
01139 extern int quietModeRequested;
01140
01141 #if defined(_WIN32)
01142 #include <windows.h>
01143 #define SET_ENV_VAR(key, value) SetEnvironmentVariable(key, value)
01144 #else
01145 #define SET_ENV_VAR(key, value) setenv(key, value, 0)
01146 #endif
01147
01148 #include <limits.h>
01149
01150 #if CMK_LOCKLESS_QUEUE
01151 #define DefaultDataNodeSize 2048
01152 #define DefaultMaxDataNodes 2048
01153 extern int DataNodeSize;
01154 extern int MaxDataNodes;
01155 extern int QueueUpperBound;
01156 extern int DataNodeWrap;
01157 extern int QueueWrap;
01158 extern int messageQueueOverflow;
01159
01160 int power_of_two_check(int n)
01161 {
01162 return (n > 0 && (n & (n - 1)) == 0);
01163 }
01164
01165
01166 void check_and_set_queue_parameters()
01167 {
01168 if(DataNodeSize <= 0 || MaxDataNodes <= 0 || !power_of_two_check(DataNodeSize) || !power_of_two_check(MaxDataNodes))
01169 {
01170 CmiPrintf("MessageQueues: MessageQueueNodeSize: %d, Check that this value is > 0 and a power of 2.\n", DataNodeSize);
01171 CmiPrintf("MessageQueues: MessageQueueNodes: %d, Check that this value is > 0 and a power of 2.\n", MaxDataNodes);
01172 CmiAbort("Invalid MessageQueue Parameters");
01173 }
01174 QueueUpperBound = DataNodeSize * MaxDataNodes;
01175 DataNodeWrap = DataNodeSize - 1;
01176 QueueWrap = QueueUpperBound - 1;
01177 }
01178 #endif
01179
01180
01181 void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
01182 int _ii;
01183 int tmp;
01184
01185 char *stdoutbase,*stdoutpath;
01186
01187
01188 #if CMK_WITH_STATS
01189 MSG_STATISTIC = CmiGetArgFlag(argv, "+msgstatistic");
01190 #endif
01191
01192 if (CmiGetArgFlagDesc(argv,"++quiet","Omit non-error runtime messages")) {
01193 quietModeRequested = quietMode = 1;
01194 }
01195
01196 CmiInitHwlocTopology();
01197
01198
01199 _Cmi_mynodesize = 1;
01200
01201 int ppnSet = 0;
01202 if (!(ppnSet = CmiGetArgInt(argv,"+ppn", &_Cmi_mynodesize)))
01203 ppnSet = CmiGetArgInt(argv,"++ppn", &_Cmi_mynodesize);
01204
01205 int npes = 1;
01206 int plusPSet = CmiGetArgInt(argv,"+p",&npes);
01207
01208 int auto_provision = CmiGetArgFlagDesc(argv, "+auto-provision", "fully utilize available resources");
01209 auto_provision |= CmiGetArgFlagDesc(argv, "+autoProvision", "fully utilize available resources");
01210 int onewth_per_host = CmiGetArgFlagDesc(argv, "+oneWthPerHost", "assign one worker thread per host");
01211 int onewth_per_socket = CmiGetArgFlagDesc(argv, "+oneWthPerSocket", "assign one worker thread per socket");
01212 int onewth_per_core = CmiGetArgFlagDesc(argv, "+oneWthPerCore", "assign one worker thread per core");
01213 int onewth_per_pu = CmiGetArgFlagDesc(argv, "+oneWthPerPU", "assign one worker thread per PU");
01214 int onewth_active = (onewth_per_host > 0) + (onewth_per_socket > 0) + (onewth_per_core > 0) + (onewth_per_pu > 0);
01215 if (onewth_active > 1 || onewth_active + (plusPSet || ppnSet) + auto_provision > 1)
01216 {
01217 CmiError("Error: Only one of +auto-provision, +oneWthPer(Host|Socket|Core|PU), or +p/++ppn is allowed.\n");
01218 exit(1);
01219 }
01220
01221 #if ! CMK_SMP
01222 if (plusPSet && npes != 1)
01223 {
01224 fprintf(stderr,
01225 "To use multiple processors, you must run this program as:\n"
01226 " > charmrun +p%d %s <args>\n"
01227 "or build the %s-smp version of Charm++.\n",
01228 npes,argv[0],CMK_MACHINE_NAME);
01229 exit(1);
01230 }
01231
01232 if ((_Cmi_mynodesize > 1 && _Cmi_mynode == 0) || onewth_per_socket || onewth_per_core || onewth_per_pu)
01233 {
01234 CmiError("Error: +oneWthPer(Socket|Core|PU) and +ppn can only be used in SMP mode.\n");
01235 exit(1);
01236 }
01237 #else
01238 if (onewth_active || auto_provision)
01239 {
01240 SET_ENV_VAR("CmiProcessPerHost", "1");
01241
01242 int ppn;
01243 if (onewth_per_host)
01244 {
01245 ppn = 1;
01246 SET_ENV_VAR("CmiOneWthPerHost", "1");
01247 }
01248 else if (onewth_per_socket)
01249 {
01250 ppn = CmiHwlocTopologyLocal.num_sockets;
01251 SET_ENV_VAR("CmiOneWthPerSocket", "1");
01252 }
01253 else if (onewth_per_core)
01254 {
01255 ppn = CmiHwlocTopologyLocal.num_cores;
01256 SET_ENV_VAR("CmiOneWthPerCore", "1");
01257 }
01258 else
01259 {
01260 ppn = CmiHwlocTopologyLocal.num_pus;
01261 SET_ENV_VAR("CmiOneWthPerPU", "1");
01262 }
01263 # if !CMK_MULTICORE
01264
01265 if (ppn + 1 > CmiHwlocTopologyLocal.num_pus)
01266 --ppn;
01267
01268 if (ppn == 0)
01269 ppn = 1;
01270 # endif
01271
01272 if (ppn <= 0)
01273 {
01274 CmiError("Error: Invalid request for %d PEs\n", ppn);
01275 exit(1);
01276 }
01277
01278 _Cmi_mynodesize = ppn;
01279 }
01280 else if (plusPSet)
01281 {
01282 if (ppnSet && _Cmi_mynodesize != npes)
01283 {
01284
01285 CmiError("Error: p != ppn, must not have inconsistent values. (%d != %d)\n"
01286 "Standalone invocation should use only one of [+p, +ppn, ++ppn].\n", npes, _Cmi_mynodesize);
01287 exit(1);
01288 }
01289 else
01290 {
01291 _Cmi_mynodesize = npes;
01292 }
01293 }
01294 # if CMK_NET_VERSION || CMK_IBVERBS || CMK_MULTICORE
01295 # if CMK_MULTICORE
01296 else if (!ppnSet)
01297 # else
01298 else if (!ppnSet && Cmi_charmrun_fd == -1)
01299 # endif
01300 {
01301 if (!quietMode)
01302 {
01303 printf("Charm++> No provisioning arguments specified. Running with a single PE.\n"
01304 " Use +auto-provision to fully subscribe resources or +p1 to silence this message.\n");
01305 }
01306 }
01307 # endif
01308 #endif
01309
01310
01311
01312 networkProgressPeriod = NETWORK_PROGRESS_PERIOD_DEFAULT;
01313 CmiGetArgInt(argv, "+networkProgressPeriod", &networkProgressPeriod);
01314
01315
01316
01317
01318
01319
01320 #if CMK_WITH_STATS
01321 if ( MSG_STATISTIC)
01322 {
01323 for(_ii=0; _ii<22; _ii++)
01324 msg_histogram[_ii] = 0;
01325 }
01326 #endif
01327 #if CMK_LOCKLESS_QUEUE
01328
01329 if (!CmiGetArgIntDesc(argv,"+MessageQueueNodes",&MaxDataNodes, "The size of the message queue static arrays")) {
01330 MaxDataNodes = DefaultMaxDataNodes;
01331 }
01332 if (!CmiGetArgIntDesc(argv,"+MessageQueueNodeSize",&DataNodeSize, "The size of the message queue data nodes")) {
01333 DataNodeSize = DefaultDataNodeSize;
01334 }
01335 check_and_set_queue_parameters();
01336 #endif
01337
01338 LrtsInit(&argc, &argv, &_Cmi_numnodes, &_Cmi_mynode);
01339
01340 #if MACHINE_DEBUG_LOG
01341 char ln[200];
01342 sprintf(ln,"debugLog.%d", _Cmi_mynode);
01343 debugLog=fopen(ln,"w");
01344 if (debugLog == NULL)
01345 {
01346 CmiAbort("debug file not open\n");
01347 }
01348 #endif
01349
01350
01351 if (_Cmi_mynode==0) {
01352 #if !CMK_SMP
01353 if (!quietMode) printf("Charm++> Running in non-SMP mode: %d processes (PEs)\n", _Cmi_numnodes);
01354 MACHSTATE1(4,"running nonsmp %d", _Cmi_mynode)
01355 #else
01356
01357 #if !CMK_MULTICORE
01358 if (!quietMode) {
01359
01360 int commThdsPerProcess = (Cmi_smp_mode_setting != COMM_THREAD_NOT_EXIST);
01361 int totalPes = CmiNumNodes() * _Cmi_mynodesize;
01362 printf("Charm++> Running in SMP mode: %d processes, %d worker threads (PEs) + %d comm threads per process, %d PEs total\n",
01363 CmiNumNodes(), _Cmi_mynodesize, commThdsPerProcess, totalPes);
01364 }
01365 if (Cmi_smp_mode_setting == COMM_THREAD_SEND_RECV) {
01366 if (!quietMode) printf("Charm++> The comm. thread both sends and receives messages\n");
01367 } else if (Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV) {
01368 if (!quietMode) printf("Charm++> The comm. thread only receives messages, while work threads send messages\n");
01369 } else if (Cmi_smp_mode_setting == COMM_WORK_THREADS_SEND_RECV) {
01370 if (!quietMode) printf("Charm++> Both comm. thread and worker thread send and messages\n");
01371 } else if (Cmi_smp_mode_setting == COMM_THREAD_NOT_EXIST) {
01372 if (!quietMode) printf("Charm++> There's no comm. thread. Work threads both send and receive messages\n");
01373 } else {
01374 CmiAbort("Charm++> Invalid SMP mode setting\n");
01375 }
01376 #else
01377 if (!quietMode) printf("Charm++> Running in Multicore mode: %d threads (PEs)\n", _Cmi_mynodesize);
01378 #endif
01379
01380 #endif
01381 }
01382
01383 CmiCreatePartitions(argv);
01384
01385 _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
01386 Cmi_nodestart = _Cmi_mynode * _Cmi_mynodesize;
01387 Cmi_argvcopy = CmiCopyArgs(argv);
01388 Cmi_argv = argv;
01389 Cmi_startfn = fn;
01390 Cmi_usrsched = usched;
01391
01392 if ( CmiGetArgStringDesc(argv,"+stdout",&stdoutbase,"base filename to redirect partition stdout to") ) {
01393 stdoutpath = (char *)malloc(strlen(stdoutbase) + 30);
01394 sprintf(stdoutpath, stdoutbase, CmiMyPartition(), CmiMyPartition(), CmiMyPartition());
01395 if ( ! strcmp(stdoutpath, stdoutbase) ) {
01396 sprintf(stdoutpath, "%s.%d", stdoutbase, CmiMyPartition());
01397 }
01398 if ( CmiMyPartition() == 0 && CmiMyNode() == 0 && !quietMode) {
01399 printf("Redirecting stdout to files %s through %d\n",stdoutpath,CmiNumPartitions()-1);
01400 }
01401 if ( ! freopen(stdoutpath, "a", stdout) ) {
01402 fprintf(stderr,"Rank %d failed redirecting stdout to file %s: %s\n", CmiMyNodeGlobal(), stdoutpath,
01403 strerror(errno));
01404 CmiAbort("Error redirecting stdout to file.");
01405 }
01406 _writeToStdout = 0;
01407 free(stdoutpath);
01408 }
01409 #if CMK_SMP
01410 comm_mutex=CmiCreateLock();
01411 #endif
01412
01413 #if CMK_USE_PXSHM
01414 CmiInitPxshm(argv);
01415 #endif
01416 #if CMK_USE_XPMEM
01417 CmiInitXpmem(argv);
01418 #endif
01419 #if CMK_USE_CMA
01420 cma_works = 1;
01421 if (CmiGetArgFlagDesc(argv,"+cma_enable_all","Ignore default thresholds & Enable use of CMA for all intranode SHM transport")) {
01422 cma_min_threshold = 0U;
01423 cma_max_threshold = INT_MAX;
01424 } else {
01425
01426 if(!CmiGetArgIntDesc(argv,"+cma_min_threshold", &cma_min_threshold,"CMA Message size (Bytes) lower bound")) {
01427
01428 cma_min_threshold = CMK_CMA_MIN;
01429 }
01430
01431 if(!CmiGetArgIntDesc(argv,"+cma_max_threshold", &cma_max_threshold,"CMA Message size (Bytes) upper bound")) {
01432
01433 cma_max_threshold = CMK_CMA_MAX;
01434 }
01435
01436 if (CmiGetArgFlagDesc(argv,"+cma_disable","Disable use of CMA for SHM transport")) {
01437 cma_works = 0;
01438 cma_reg_msg = false;
01439 }
01440 }
01441
01442 if(cma_works) {
01443
01444 cma_works = CmiInitCma();
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454 cma_reg_msg = 0;
01455
01456
01457 if(cma_reg_msg)
01458 CmiDisplayCMAThresholds(cma_min_threshold, cma_max_threshold);
01459 }
01460 #endif
01461
01462
01463 #if CMK_BROADCAST_HYPERCUBE
01464
01465 tmp = CmiNumNodes()-1;
01466 CmiNodesDim = 0;
01467 while (tmp>0) {
01468 CmiNodesDim++;
01469 tmp = tmp >> 1;
01470 }
01471 if (CmiNumNodes()==1) CmiNodesDim=1;
01472 #endif
01473
01474 CsvInitialize(CmiNodeState, NodeState);
01475 CmiNodeStateInit(&CsvAccess(NodeState));
01476
01477 #if CMK_OFFLOAD_BCAST_PROCESS
01478
01479 CsvInitialize(CMIQueue, procBcastQ);
01480 #if CMK_NODE_QUEUE_AVAILABLE
01481 CsvInitialize(CMIQueue, nodeBcastQ);
01482 #endif
01483 #endif
01484
01485 #if CMK_SMP && CMK_LEVERAGE_COMMTHREAD
01486 CsvInitialize(CMIQueue, notifyCommThdMsgBuffer);
01487 #endif
01488
01489 CmiStartThreads(argv);
01490
01491 ConverseRunPE(initret);
01492 }
01493
01494 void ConverseCommonInit(char **argv);
01495 void CthInit(char **argv);
01496 static void ConverseRunPE(int everReturn) {
01497 CmiState cs;
01498 char** CmiMyArgv;
01499
01500 #if CMK_CCS_AVAILABLE
01501
01512 CpvInitialize(int, cmiArgDebugFlag);
01513 CpvAccess(cmiArgDebugFlag) = 0;
01514 #endif
01515
01516 LrtsPreCommonInit(everReturn);
01517
01518 #if CMK_OFFLOAD_BCAST_PROCESS
01519 int createQueue = 1;
01520 #if CMK_SMP
01521 #if CMK_SMP_NO_COMMTHD
01522
01523 if (CmiMyRank()) createQueue = 0;
01524 #else
01525 if (CmiMyRank()<CmiMyNodeSize()) createQueue = 0;
01526 #endif
01527 #endif
01528
01529 if (createQueue) {
01530 CsvAccess(procBcastQ) = CMIQueueCreate();
01531 #if CMK_NODE_QUEUE_AVAILABLE
01532 CsvAccess(nodeBcastQ) = CMIQueueCreate();
01533 #endif
01534 }
01535 #endif
01536
01537 CmiNodeAllBarrier();
01538
01539 cs = CmiGetState();
01540 CpvInitialize(void *,CmiLocalQueue);
01541 CpvAccess(CmiLocalQueue) = cs->localqueue;
01542
01543 if (CmiMyRank())
01544 CmiMyArgv=CmiCopyArgs(Cmi_argvcopy);
01545 else
01546 CmiMyArgv=Cmi_argv;
01547
01548 CthInit(CmiMyArgv);
01549 #if CMK_OMP
01550 CmiNodeAllBarrier();
01551 #endif
01552
01553
01554
01555 CpvInitialize(unsigned , networkProgressCount);
01556 CpvAccess(networkProgressCount) = 0;
01557
01558 ConverseCommonInit(CmiMyArgv);
01559 #if CMK_OMP
01560 CpvAccess(CmiSuspendedTaskQueue) = (void *)CMIQueueCreate();
01561 CmiNodeAllBarrier();
01562 #endif
01563
01564
01565
01566 #if CMK_SMP
01567 {
01568 CmiIdleState *sidle=CmiNotifyGetState();
01569 CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)sidle);
01570 CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)sidle);
01571 }
01572 #else
01573 CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle, NULL);
01574 CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle, NULL);
01575 #endif
01576
01577
01578 LrtsPostCommonInit(everReturn);
01579
01580 #if CMK_SMP && CMK_LEVERAGE_COMMTHREAD
01581 CmiInitNotifyCommThdScheme();
01582 #endif
01583
01584
01585 _immediateReady = 1;
01586
01587
01588 if (CmiMyRank() == CmiMyNodeSize()) {
01589 Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
01590 if(!CharmLibInterOperate) {
01591 while (1) CommunicationServerThread(5);
01592 }
01593 } else {
01594 if (!everReturn) {
01595 Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
01596 if (Cmi_usrsched==0) CsdScheduler(-1);
01597 if(!CharmLibInterOperate) {
01598 ConverseExit();
01599 }
01600 }
01601 }
01602 }
01603
01604
01605
01606 static INLINE_KEYWORD void AdvanceCommunication(int whenidle) {
01607 int doProcessBcast = 1;
01608
01609 #if CMK_USE_PXSHM
01610 CommunicationServerPxshm();
01611 #endif
01612 #if CMK_USE_XPMEM
01613 CommunicationServerXpmem();
01614 #endif
01615
01616 LrtsAdvanceCommunication(whenidle);
01617
01618 #if CMK_OFFLOAD_BCAST_PROCESS
01619 #if CMK_SMP_NO_COMMTHD
01620
01621 if (CmiMyRank()) doProcessBcast = 0;
01622 #endif
01623 if (doProcessBcast) processBcastQs();
01624 #endif
01625
01626 #if CMK_IMMEDIATE_MSG
01627 #if !CMK_SMP
01628 CmiHandleImmediate();
01629 #endif
01630 #if CMK_SMP && CMK_SMP_NO_COMMTHD
01631 if (CmiMyRank()==0) CmiHandleImmediate();
01632 #endif
01633 #endif
01634 }
01635
01636 void ConverseCommonExit(void);
01637
01638 static void CommunicationServer(int sleepTime) {
01639 #if CMK_SMP
01640 AdvanceCommunication(1);
01641
01642 if (std::atomic_load_explicit(&commThdExit, std::memory_order_acquire) == CmiMyNodeSize()) {
01643 MACHSTATE(2, "CommunicationServer exiting {");
01644 LrtsDrainResources();
01645 MACHSTATE(2, "} CommunicationServer EXIT");
01646
01647 ConverseCommonExit();
01648
01649 #if CMK_USE_XPMEM
01650 CmiExitXpmem();
01651 #endif
01652 CmiNodeAllBarrier();
01653 LrtsExit(_exitcode);
01654 if(CharmLibInterOperate) {
01655 ckExitComplete = 1;
01656 CmiNodeAllBarrier();
01657 }
01658 }
01659 #endif
01660 }
01661
01662 void CommunicationServerThread(int sleepTime) {
01663 CommunicationServer(sleepTime);
01664 #if CMK_IMMEDIATE_MSG
01665 CmiHandleImmediate();
01666 #endif
01667 }
01668
01669 void ConverseExit(int exitcode) {
01670 int i;
01671 if (quietModeRequested) quietMode = 1;
01672 #if !CMK_SMP || CMK_SMP_NO_COMMTHD
01673 LrtsDrainResources();
01674 #else
01675 if(Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV
01676 || Cmi_smp_mode_setting == COMM_THREAD_NOT_EXIST)
01677 LrtsDrainResources();
01678 #endif
01679
01680 ConverseCommonExit();
01681
01682 #if CMK_WITH_STATS
01683 if (MSG_STATISTIC)
01684 {
01685 for(i=0; i<22; i++)
01686 {
01687 CmiPrintf("[MSG PE:%d]", CmiMyPe());
01688 if(msg_histogram[i] >0)
01689 CmiPrintf("(%d:%d) ", 1<<i, msg_histogram[i]);
01690 }
01691 CmiPrintf("\n");
01692 }
01693 #endif
01694
01695 #if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
01696 if (CmiMyPe() == 0)
01697 CmiPrintf("[Partition %d][Node %d] End of program\n",CmiMyPartition(),CmiMyNode());
01698 #endif
01699
01700 #if !CMK_SMP || CMK_BLUEGENEQ || CMK_PAMI_LINUX_PPC8
01701 #if CMK_USE_PXSHM
01702 CmiExitPxshm();
01703 #endif
01704 #if CMK_USE_XPMEM
01705 CmiExitXpmem();
01706 #endif
01707 LrtsExit(exitcode);
01708 #else
01709
01710 if (CmiMyRank() == 0)
01711 _exitcode = exitcode;
01712 std::atomic_fetch_add_explicit(&commThdExit, 1, std::memory_order_release);
01713 CmiNodeAllBarrier();
01714 #if CMK_SMP_NO_COMMTHD
01715 #if CMK_USE_XPMEM
01716 if (CmiMyRank() == 0) CmiExitXpmem();
01717 CmiNodeAllBarrier();
01718 #endif
01719 if (CmiMyRank() == 0) LrtsExit();
01720 #endif
01721 CmiYield();
01722 if (!CharmLibInterOperate || userDrivenMode) {
01723 while (1) {
01724 CmiYield();
01725 }
01726 }
01727 #endif
01728 }
01729
01730
01731 void CmiAbortHelper(const char *source, const char *message, const char *suggestion,
01732 int tellDebugger, int framesToSkip) {
01733 if (tellDebugger)
01734 CpdAborting(message);
01735
01736 if (CmiNumPartitions() == 1) {
01737 CmiError("------------- Processor %d Exiting: %s ------------\n"
01738 "Reason: %s\n", CmiMyPe(), source, message);
01739 } else {
01740 CmiError("------- Partition %d Processor %d Exiting: %s ------\n"
01741 "Reason: %s\n", CmiMyPartition(), CmiMyPe(), source, message);
01742 }
01743
01744 if (suggestion && suggestion[0])
01745 CmiError("Suggestion: %s\n", suggestion);
01746
01747 CmiPrintStackTrace(framesToSkip);
01748
01749 #if CMK_USE_PXSHM
01750 CmiExitPxshm();
01751 #endif
01752 #if CMK_USE_XPMEM
01753 CmiExitXpmem();
01754 #endif
01755 LrtsAbort(message);
01756 }
01757
01758 void CmiAbort(const char *message) {
01759 CmiAbortHelper("Called CmiAbort", message, NULL, 1, 0);
01760 CMI_NORETURN_FUNCTION_END
01761 }
01762
01763
01764 void *CmiGetNonLocal(void) {
01765 CmiState cs = CmiGetState();
01766 void *msg = NULL;
01767 #if !CMK_SMP || CMK_SMP_NO_COMMTHD
01768
01776 #if CMK_CCS_AVAILABLE
01777 if (CmiNumPes() == 1 && CmiNumPartitions() == 1 && ccsRunning != 1) return NULL;
01778 #else
01779 if (CmiNumPes() == 1 && CmiNumPartitions() == 1) return NULL;
01780 #endif
01781 #endif
01782
01783 MACHSTATE2(3, "[%p] CmiGetNonLocal begin %d{", cs, CmiMyPe());
01784
01785 #if CMK_MACH_SPECIALIZED_QUEUE
01786 msg = LrtsSpecializedQueuePop();
01787 #else
01788 CmiIdleLock_checkMessage(&cs->idle);
01789
01790
01791 msg = CMIQueuePop(cs->recv);
01792 #endif
01793 #if (!CMK_SMP || CMK_SMP_NO_COMMTHD) && !CMK_MULTICORE
01794 if (!msg) {
01795 AdvanceCommunication(0);
01796 #if CMK_MACH_SPECIALIZED_QUEUE
01797 msg = LrtsSpecializedQueuePop();
01798 #else
01799 msg = CMIQueuePop(cs->recv);
01800 #endif
01801 }
01802 #else
01803
01804 #endif
01805 #if CMK_CCS_AVAILABLE
01806 if(msg != NULL && CmiNumPes() == 1 && CmiNumPartitions() == 1 )
01807 {
01808 ccsRunning = 0;
01809 }
01810 #endif
01811
01812 MACHSTATE3(3,"[%p] CmiGetNonLocal from queue %p with msg %p end }",CmiGetState(),(cs->recv), msg);
01813
01814 return msg;
01815 }
01816
01817 #if CMK_NODE_QUEUE_AVAILABLE
01818 void *CmiGetNonLocalNodeQ(void) {
01819 char *result = 0;
01820
01821 #if CMK_MACH_SPECIALIZED_QUEUE && CMK_MACH_SPECIALIZED_MUTEX
01822 if (!LrtsSpecializedNodeQueueEmpty()) {
01823 if (LrtsSpecializedMutexTryAcquire() == 0) {
01824 result = LrtsSpecializedNodeQueuePop();
01825 LrtsSpecializedMutexRelease();
01826 }
01827 }
01828 #elif CMK_MACH_SPECIALIZED_QUEUE
01829 if(!LrtsSpecializedNodeQueueEmpty()) {
01830 if(CmiTryLock(CsvAccess(NodeState).CmiNodeRecvLock) == 0) {
01831 result = LrtsSpecializedNodeQueuePop();
01832 CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
01833 }
01834
01835 }
01836 #else
01837 CmiState cs = CmiGetState();
01838 CmiIdleLock_checkMessage(&cs->idle);
01839 #if CMK_LOCKLESS_QUEUE
01840 if (!MPMCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
01841 #else
01842 if (!CMIQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
01843 #endif
01844 MACHSTATE1(3,"CmiGetNonLocalNodeQ begin %d {", CmiMyPe());
01845 #if CMK_LOCKLESS_QUEUE
01846 result = (char *) MPMCQueuePop(CsvAccess(NodeState).NodeRecv);
01847 #else
01848 CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
01849 result = (char *) CMIQueuePop(CsvAccess(NodeState).NodeRecv);
01850 CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
01851 #endif
01852 MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
01853 }
01854 #endif
01855 return result;
01856
01857 }
01858 #endif
01859
01860
01861 static CmiIdleState *CmiNotifyGetState(void) {
01862 CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
01863 s->sleepMs=0;
01864 s->nIdles=0;
01865 s->cs=CmiGetState();
01866 return s;
01867 }
01868
01869 static void CmiNotifyBeginIdle(CmiIdleState *s) {
01870 if(s!= NULL){
01871 s->sleepMs=0;
01872 s->nIdles=0;
01873 }
01874 LrtsBeginIdle();
01875 }
01876
01877
01878 #define SPINS_BEFORE_SLEEP 20
01879 static void CmiNotifyStillIdle(CmiIdleState *s) {
01880 MACHSTATE1(2,"still idle (%d) begin {",CmiMyPe())
01881 #if (!CMK_SMP || CMK_SMP_NO_COMMTHD) && !CMK_MULTICORE
01882 AdvanceCommunication(1);
01883 #else
01884 LrtsPostNonLocal();
01885
01886 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
01887 if (_Cmi_sleepOnIdle)
01888 #endif
01889 {
01890 s->nIdles++;
01891 if (s->nIdles>SPINS_BEFORE_SLEEP) {
01892 s->sleepMs+=2;
01893 if (s->sleepMs>10) s->sleepMs=10;
01894 }
01895
01896 if (s->sleepMs>0) {
01897 MACHSTATE1(2,"idle lock(%d) {",CmiMyPe())
01898 CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
01899 MACHSTATE1(2,"} idle lock(%d)",CmiMyPe())
01900 }
01901 }
01902 #endif
01903 LrtsStillIdle();
01904 CsdResetPeriodic();
01905 MACHSTATE1(2,"still idle (%d) end {",CmiMyPe())
01906 }
01907
01908
01909 void CmiNotifyIdle(void) {
01910 AdvanceCommunication(1);
01911 CmiYield();
01912 LrtsNotifyIdle();
01913 }
01914
01915
01916 static char *CopyMsg(char *msg, int len) {
01917 char *copy = (char *)CmiAlloc(len);
01918 #if CMK_ERROR_CHECKING
01919 if (!copy) {
01920 CmiAbort("Error: out of memory in machine layer\n");
01921 }
01922 #endif
01923 memcpy(copy, msg, len);
01924 return copy;
01925 }
01926
01927
01928
01929 int CmiBarrier(void) {
01930 #if CMK_SMP
01931
01932 CmiNodeAllBarrier();
01933 #endif
01934 #if ( CMK_SMP && !CMK_SMP_NO_COMMTHD)
01935 if (CmiMyRank() == CmiMyNodeSize())
01936 {
01937 #else
01938 if (CmiMyRank() == 0)
01939 {
01940 #endif
01941 LrtsBarrier();
01942 }
01943 #if CMK_SMP
01944 CmiNodeAllBarrier();
01945 #endif
01946 return 0;
01947 }
01948
01949
01950 #if CMK_USE_COMMON_LOCK
01951 #if CMK_SHARED_VARS_UNAVAILABLE
01952
01953 LrtsNodeLock LrtsCreateLock(void){ return 0; }
01954 void LrtsLock(LrtsNodeLock lock){ (lock)++; }
01955 void LrtsUnlock(LrtsNodeLock lock){ (lock)--; }
01956 int LrtsTryLock(LrtsNodeLock lock){ return ((lock)?1:((lock)=1,0)); }
01957 void LrtsDestroyLock(LrtsNodeLock lock){ }
01958
01959 #else
01960 #if CMK_SHARED_VARS_NT_THREADS
01961
01962 LrtsNodeLock LrtsCreateLock(void){
01963 HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
01964 return hMutex;
01965 }
01966 void LrtsLock(LrtsNodeLock lock){
01967 WaitForSingleObject(lock, INFINITE);
01968 }
01969 void LrtsUnlock(LrtsNodeLock lock){
01970 ReleaseMutex(lock);
01971 }
01972 int LrtsTryLock(LrtsNodeLock lock){
01973 return !!WaitForSingleObject(lock, 0);
01974 }
01975 void LrtsDestroyLock(LrtsNodeLock lock){
01976 CloseHandle(lock);
01977 }
01978
01979 #else
01980 LrtsNodeLock LrtsCreateLock(void){
01981 void *l = malloc(sizeof(pthread_mutex_t));
01982 pthread_mutex_init((pthread_mutex_t *)l,(pthread_mutexattr_t *)0);
01983 return (LrtsNodeLock)l;
01984 }
01985 void LrtsLock(LrtsNodeLock lock){
01986 pthread_mutex_lock((pthread_mutex_t*)lock);
01987 }
01988 void LrtsUnlock(LrtsNodeLock lock){
01989 pthread_mutex_unlock((pthread_mutex_t*)lock);
01990 }
01991 int LrtsTryLock(LrtsNodeLock lock){
01992 return pthread_mutex_trylock((pthread_mutex_t*)lock);
01993 }
01994 void LrtsDestroyLock(LrtsNodeLock lock){
01995 pthread_mutex_destroy((pthread_mutex_t*)lock);
01996 free(lock);
01997 }
01998 #endif
01999
02000 #endif //CMK_SHARED_VARS_UNAVAILABLE
02001 #endif //CMK_USE_COMMON_LOCK