00001
00005 #define CONVERSE_MACHINE_BROADCAST_C_
00006 #include "spanningTree.h"
00007
00008 CmiCommHandle CmiSendNetworkFunc(int destPE, int size, char *msg, int mode);
00009
00010 static void handleOneBcastMsg(int size, char *msg) {
00011 CmiAssert(CMI_BROADCAST_ROOT(msg)!=0);
00012 #if CMK_OFFLOAD_BCAST_PROCESS
00013 if (CMI_BROADCAST_ROOT(msg)>0) {
00014 CMIQueuePush(CsvAccess(procBcastQ), msg);
00015 } else {
00016 #if CMK_NODE_QUEUE_AVAILABLE
00017 CMIQueuePush(CsvAccess(nodeBcastQ), msg);
00018 #endif
00019 }
00020 #else
00021 if (CMI_BROADCAST_ROOT(msg)>0) {
00022 processProcBcastMsg(size, msg);
00023 } else {
00024 #if CMK_NODE_QUEUE_AVAILABLE
00025 processNodeBcastMsg(size, msg);
00026 #endif
00027 }
00028 #endif
00029 }
00030
00031 static void processBcastQs(void) {
00032 #if CMK_OFFLOAD_BCAST_PROCESS
00033 char *msg;
00034 do {
00035 msg = CMIQueuePop(CsvAccess(procBcastQ));
00036 if (!msg) break;
00037 MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p begin{", CmiMyNode(), msg);
00038 processProcBcastMsg(CMI_MSG_SIZE(msg), msg);
00039 MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p end}", CmiMyNode(), msg);
00040 } while (1);
00041 #if CMK_NODE_QUEUE_AVAILABLE
00042 do {
00043 msg = CMIQueuePop(CsvAccess(nodeBcastQ));
00044 if (!msg) break;
00045 MACHSTATE2(4, "[%d]: process a node-level bcast msg %p begin{", CmiMyNode(), msg);
00046 processNodeBcastMsg(CMI_MSG_SIZE(msg), msg);
00047 MACHSTATE2(4, "[%d]: process a node-level bcast msg %p end}", CmiMyNode(), msg);
00048 } while (1);
00049 #endif
00050 #endif
00051 }
00052
00053
00054 static INLINE_KEYWORD void forwardProcBcastMsg(int size, char *msg) {
00055 #if CMK_BROADCAST_SPANNING_TREE
00056 SendSpanningChildrenProc(size, msg);
00057 #elif CMK_BROADCAST_HYPERCUBE
00058 SendHyperCubeProc(size, msg);
00059 #endif
00060 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00061
00062 if (CmiNumNodes()>1 && CmiGetReference(msg)>1) {
00063 void *newmsg;
00064 newmsg = CopyMsg(msg, size);
00065 CmiFree(msg);
00066 msg = newmsg;
00067 }
00068 #endif
00069 }
00070
00071 static INLINE_KEYWORD void processProcBcastMsg(int size, char *msg) {
00072
00073
00074
00075 CmiAssert(CMI_DEST_RANK(msg)==0);
00076
00077
00078
00079
00080 #if CMK_ONESIDED_IMPL
00081 if(!CMI_IS_ZC_BCAST(msg))
00082 #endif
00083 forwardProcBcastMsg(size, msg);
00084
00085 CmiPushPE(0, msg);
00086
00087 }
00088
00089 #if CMK_NODE_QUEUE_AVAILABLE
00090
00091 static INLINE_KEYWORD void forwardNodeBcastMsg(int size, char *msg) {
00092 #if CMK_BROADCAST_SPANNING_TREE
00093 SendSpanningChildrenNode(size, msg);
00094 #elif CMK_BROADCAST_HYPERCUBE
00095 SendHyperCubeNode(size, msg);
00096 #endif
00097 }
00098
00099
00100 void CmiForwardNodeBcastMsg(int size, char *msg) {
00101 forwardNodeBcastMsg(size, msg);
00102 }
00103
00104 static INLINE_KEYWORD void processNodeBcastMsg(int size, char *msg) {
00105
00106
00107 #if CMK_ONESIDED_IMPL
00108 if(!CMI_IS_ZC_BCAST(msg))
00109 #endif
00110 forwardNodeBcastMsg(size, msg);
00111
00112
00113
00114
00115
00116
00117
00118
00119 CmiPushNode(msg);
00120 }
00121 #endif
00122
00123
00124 void CmiForwardProcBcastMsg(int size, char *msg) {
00125 forwardProcBcastMsg(size, msg);
00126 }
00127
00128 #if CMK_SMP
00129
00130 void CmiForwardMsgToPeers(int size, char *msg) {
00131 SendToPeers(size, msg);
00132 }
00133 #endif
00134
00135 static void SendSpanningChildren(int size, char *msg, int rankToAssign, int startNode) {
00136 #if CMK_BROADCAST_SPANNING_TREE
00137 int i, oldRank;
00138 char *newmsg;
00139
00140 oldRank = CMI_DEST_RANK(msg);
00141
00142 CMI_DEST_RANK(msg) = rankToAssign;
00143
00144 CmiAssert(startNode >=0 && startNode<CmiNumNodes());
00145 if (_topoTree == NULL) {
00146 for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
00147 int nd = CmiMyNode()-startNode;
00148 if (nd<0) nd+=CmiNumNodes();
00149 nd = BROADCAST_SPANNING_FACTOR*nd + i;
00150 if (nd > CmiNumNodes() - 1) break;
00151 nd += startNode;
00152 nd = nd%CmiNumNodes();
00153 CmiAssert(nd>=0 && nd!=CmiMyNode());
00154 #if CMK_BROADCAST_USE_CMIREFERENCE
00155 CmiReference(msg);
00156 CmiSendNetworkFunc(CmiNodeFirst(nd), size, msg, BCAST_SYNC);
00157 #else
00158 newmsg = CopyMsg(msg, size);
00159 CmiSendNetworkFunc(CmiNodeFirst(nd), size, newmsg, BCAST_SYNC);
00160 #endif
00161 }
00162 } else {
00163 int parent, child_count;
00164 int *children = NULL;
00165 if (startNode == 0) {
00166 child_count = _topoTree->child_count;
00167 children = _topoTree->children;
00168
00169 } else {
00170 get_topo_tree_nbs(startNode, &parent, &child_count, &children);
00171 }
00172 for (i=0; i < child_count; i++) {
00173 int nd = children[i];
00174 #if CMK_BROADCAST_USE_CMIREFERENCE
00175 CmiReference(msg);
00176 CmiSendNetworkFunc(CmiNodeFirst(nd), size, msg, BCAST_SYNC);
00177 #else
00178 newmsg = CopyMsg(msg, size);
00179
00180 CmiSendNetworkFunc(CmiNodeFirst(nd), size, newmsg, BCAST_SYNC);
00181 #endif
00182 }
00183 }
00184 CMI_DEST_RANK(msg) = oldRank;
00185 #endif
00186 }
00187
00188 static void SendHyperCube(int size, char *msg, int rankToAssign, int startNode) {
00189 #if CMK_BROADCAST_HYPERCUBE
00190 int i, cnt, tmp, relDist, oldRank;
00191 const int dims=CmiNodesDim;
00192
00193 oldRank = CMI_DEST_RANK(msg);
00194
00195 CMI_DEST_RANK(msg) = rankToAssign;
00196
00197
00198 relDist = CmiMyNode()-startNode;
00199 if (relDist < 0) relDist += CmiNumNodes();
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 if(relDist==0) cnt = 1<<dims;
00215 else cnt = relDist & ((~relDist)+1);
00216
00217
00218 for(cnt>>=1; cnt>0; cnt>>=1){
00219 int nd = relDist + cnt;
00220 char *newmsg;
00221 if (nd >= CmiNumNodes()) continue;
00222 nd = (nd+startNode)%CmiNumNodes();
00223
00224 CmiAssert(nd>=0 && nd!=CmiMyNode());
00225 #if CMK_BROADCAST_USE_CMIREFERENCE
00226 CmiReference(msg);
00227 CmiSendNetworkFunc(CmiNodeFirst(nd), size, msg, BCAST_SYNC);
00228 #else
00229 newmsg = CopyMsg(msg, size);
00230 CmiSendNetworkFunc(CmiNodeFirst(nd), size, newmsg, BCAST_SYNC);
00231 #endif
00232 }
00233 CMI_DEST_RANK(msg) = oldRank;
00234 #endif
00235 }
00236
00237 static void SendSpanningChildrenProc(int size, char *msg) {
00238 int startnode = CMI_BROADCAST_ROOT(msg)-1;
00239 SendSpanningChildren(size, msg, 0, startnode);
00240 #if CMK_SMP
00241
00242
00243 #if CMK_ONESIDED_IMPL
00244 if(!CMI_IS_ZC_BCAST(msg))
00245 #endif // end of CMK_ONESIDED_IMPL
00246
00247 SendToPeers(size, msg);
00248 #endif // end of CMK_SMP
00249 }
00250
00251
00252 static void SendHyperCubeProc(int size, char *msg) {
00253 int startpe = CMI_BROADCAST_ROOT(msg)-1;
00254 int startnode = CmiNodeOf(startpe);
00255 #if CMK_SMP
00256 if (startpe > CmiNumPes()) startnode = startpe - CmiNumPes();
00257 #endif
00258 SendHyperCube(size, msg, 0, startnode);
00259
00260 #if CMK_SMP
00261
00262
00263 #if CMK_ONESIDED_IMPL
00264 if(!CMI_IS_ZC_BCAST(msg))
00265 #endif // end of CMK_ONESIDED_IMPL
00266
00267 SendToPeers(size, msg);
00268 #endif // end of CMK_SMP
00269 }
00270
00271 #if CMK_NODE_QUEUE_AVAILABLE
00272 static void SendSpanningChildrenNode(int size, char *msg) {
00273 int startnode = -CMI_BROADCAST_ROOT(msg)-1;
00274 SendSpanningChildren(size, msg, DGRAM_NODEMESSAGE, startnode);
00275 }
00276 static void SendHyperCubeNode(int size, char *msg) {
00277 int startnode = -CMI_BROADCAST_ROOT(msg)-1;
00278 SendHyperCube(size, msg, DGRAM_NODEMESSAGE, startnode);
00279 }
00280 #endif
00281
00282 #if USE_COMMON_SYNC_BCAST
00283
00284 void CmiSyncBroadcastFn1(int size, char *msg) {
00285 int i, mype;
00286
00287 #if CMI_QD
00288 CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
00289 #endif
00290
00291 CMI_DEST_RANK(msg) = CmiMyRank();
00292
00293 #if CMK_BROADCAST_SPANNING_TREE
00294 CMI_SET_BROADCAST_ROOT(msg, CmiMyNode()+1);
00295 SendSpanningChildrenProc(size, msg);
00296 #elif CMK_BROADCAST_HYPERCUBE
00297 CMI_SET_BROADCAST_ROOT(msg, CmiMyNode()+1);
00298 SendHyperCubeProc(size, msg);
00299 #else
00300 mype = CmiMyPe();
00301 #if CMK_SMP
00302
00303 if(mype >= _Cmi_numpes){
00304 for(i=0; i<_Cmi_numpes; i++)
00305 CmiSyncSendFn(i, size, msg);
00306 return;
00307 }
00308 #endif
00309
00310 for ( i=mype+1; i<_Cmi_numpes; i++ )
00311 CmiSyncSendFn(i, size, msg) ;
00312
00313 for ( i=0; i<mype; i++ )
00314 CmiSyncSendFn(i, size, msg) ;
00315 #endif
00316
00317
00318 }
00319
00320 void CmiSyncBroadcastFn(int size, char *msg) {
00321 char *newmsg = msg;
00322 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00323
00324
00325 if (CmiNumNodes()>1) newmsg = CopyMsg(msg, size);
00326 #endif
00327 CmiSyncBroadcastFn1(size, newmsg);
00328 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00329 if (newmsg != msg) CmiFree(newmsg);
00330 #endif
00331 }
00332
00333 void CmiFreeBroadcastFn(int size, char *msg) {
00334 CmiSyncBroadcastFn1(size,msg);
00335 CmiFree(msg);
00336 }
00337 #else
00338 #define CmiSyncBroadcastFn1(s,m) CmiSyncBroadcastFn(s,m)
00339 #endif
00340
00341 #if USE_COMMON_ASYNC_BCAST
00342
00343 CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
00344
00345 CmiAbort("CmiAsyncBroadcastFn should never be called");
00346 return 0;
00347 }
00348 #endif
00349
00350
00351 void CmiSyncBroadcastAllFn(int size, char *msg) {
00352 char *newmsg = msg;
00353 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00354
00355
00356 if (CmiNumNodes()>1) newmsg = CopyMsg(msg, size);
00357 #endif
00358 CmiSyncSendFn(CmiMyPe(), size, newmsg) ;
00359 CmiSyncBroadcastFn1(size, newmsg);
00360 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00361 if (newmsg != msg) CmiFree(newmsg);
00362 #endif
00363 }
00364
00365 void CmiFreeBroadcastAllFn(int size, char *msg) {
00366 CmiSyncBroadcastFn1(size, msg);
00367 #if CMK_BROADCAST_SPANNING_TREE && CMK_BROADCAST_USE_CMIREFERENCE
00368
00369
00370 if (CmiNumNodes()>1 && CmiGetReference(msg)>1) {
00371 void *newmsg = CopyMsg(msg, size);
00372 CmiFree(msg);
00373 msg = newmsg;
00374 }
00375 #endif
00376 CmiSendSelf(msg);
00377 }
00378
00379 CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
00380 CmiSendSelf(CopyMsg(msg, size));
00381 return CmiAsyncBroadcastFn(size, msg);
00382 }
00383
00384 #if CMK_NODE_QUEUE_AVAILABLE
00385 #if USE_COMMON_SYNC_BCAST
00386 void CmiSyncNodeBroadcastFn(int size, char *msg) {
00387 int mynode = CmiMyNode();
00388 int i;
00389 #if CMI_QD
00390 CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
00391 #endif
00392 #if CMK_BROADCAST_SPANNING_TREE
00393 CMI_SET_BROADCAST_ROOT(msg, -CmiMyNode()-1);
00394 SendSpanningChildrenNode(size, msg);
00395 #elif CMK_BROADCAST_HYPERCUBE
00396 CMI_SET_BROADCAST_ROOT(msg, -CmiMyNode()-1);
00397 SendHyperCubeNode(size, msg);
00398 #else
00399 for (i=mynode+1; i<CmiNumNodes(); i++)
00400 CmiSyncNodeSendFn(i, size, msg);
00401 for (i=0; i<mynode; i++)
00402 CmiSyncNodeSendFn(i, size, msg);
00403 #endif
00404 }
00405
00406 void CmiFreeNodeBroadcastFn(int size, char *msg) {
00407 CmiSyncNodeBroadcastFn(size, msg);
00408 CmiFree(msg);
00409 }
00410 #endif
00411
00412 #if USE_COMMON_ASYNC_BCAST
00413 CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg) {
00414 CmiSyncNodeBroadcastFn(size, msg);
00415 return 0;
00416 }
00417 #endif
00418
00419 void CmiSyncNodeBroadcastAllFn(int size, char *msg) {
00420 CmiSyncNodeSendFn(CmiMyNode(), size, msg);
00421 CmiSyncNodeBroadcastFn(size, msg);
00422 }
00423
00424 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg) {
00425 CmiSendNodeSelf(CopyMsg(msg, size));
00426 return CmiAsyncNodeBroadcastFn(size, msg);
00427 }
00428
00429 void CmiFreeNodeBroadcastAllFn(int size, char *msg) {
00430 CmiSyncNodeBroadcastFn(size, msg);
00431
00432
00433
00434
00435
00436
00437
00438 CmiSendNodeSelf(msg);
00439 }
00440 #endif
00441
00442
00443 #if ! CMK_MULTICAST_LIST_USE_COMMON_CODE
00444
00445 void CmiSyncListSendFn(int npes, const int *pes, int len, char *msg)
00446 {
00447 LrtsSyncListSendFn(npes, pes, len, msg);
00448 }
00449
00450 CmiCommHandle CmiAsyncListSendFn(int npes, const int *pes, int len, char *msg)
00451 {
00452 return LrtsAsyncListSendFn(npes, pes, len, msg);
00453 }
00454
00455 void CmiFreeListSendFn(int npes, const int *pes, int len, char *msg)
00456 {
00457 LrtsFreeListSendFn(npes, pes, len, msg);
00458 }
00459
00460 #endif