| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| #include <assert.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| |
| #include "xmpi.h" |
| |
| int gv_xmpi_count_read = 0; |
| int gv_xmpi_listen_sock = 0; |
| int gv_xmpi_read_count = 0; |
| XMPI_Rd_Type gv_xmpi_rd; |
| int gv_xmpi_state = 0; |
| bool gv_xmpi_trace = false; |
| |
| static const char *ga_xmpi_recv_state[] = |
| { |
| "RSTATE_INIT", |
| "RSTATE_INIT2", |
| "RSTATE_HDR", |
| "RSTATE_DATA", |
| "RSTATE_DONE", |
| "RSTATE_LAST" |
| }; |
| |
| |
| |
| static void xmpi_chk_valid_comm(MPI_Comm pv_comm) |
| { |
| //assert((pv_comm & XMPI_COMM_MASK) == XMPI_COMM_MASK); |
| assert((pv_comm & ~XMPI_COMM_MASK) > 0); |
| } |
| |
| static int xmpi_recv(const char *pp_where, |
| const char *pp_where_detail, |
| int pv_sock, |
| void *pp_buf, |
| int /* pv_cnt */, |
| int *pp_cnt) |
| { |
| const char *FUNCTION = "xmpi_recv"; |
| |
| *pp_cnt = 0; |
| if (gv_xmpi_trace) |
| { |
| printf("%s: %s (%s) ENTER, sock=%d\n", |
| pp_where, |
| FUNCTION, |
| pp_where_detail, |
| pv_sock); |
| } |
| |
| const char *lp_state; |
| char *lp_hdr; |
| int lv_ret; |
| bool lv_cont; |
| |
| do |
| { |
| lv_cont = false; |
| if (gv_xmpi_trace) |
| { |
| if ((gv_xmpi_state >= XMPI_RSTATE_INIT) && |
| (gv_xmpi_state < XMPI_RSTATE_LAST)) |
| lp_state = ga_xmpi_recv_state[gv_xmpi_state]; |
| else |
| lp_state = "<unknown>"; |
| printf("%s: %s (%s) sock=%d, state=%d(%s)\n", |
| pp_where, FUNCTION, pp_where_detail, |
| pv_sock, gv_xmpi_state, lp_state); |
| } |
| switch (gv_xmpi_state) |
| { |
| case XMPI_RSTATE_INIT: |
| gv_xmpi_read_count = sizeof(XMPI_PMH_Type); |
| gv_xmpi_count_read = 0; |
| gv_xmpi_state = XMPI_RSTATE_INIT2; |
| lv_cont = true; |
| break; |
| |
| case XMPI_RSTATE_INIT2: |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) read hdr\n", |
| pp_where, FUNCTION, |
| pp_where_detail); |
| lp_hdr = (char *) &gv_xmpi_rd.iv_hdr; |
| lv_ret = (int) read(pv_sock, |
| &lp_hdr[gv_xmpi_count_read], |
| gv_xmpi_read_count - gv_xmpi_count_read); |
| if (gv_xmpi_trace) |
| { |
| if (lv_ret == -1) |
| printf("%s: %s (%s) errno=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| errno); |
| else |
| printf("%s: %s (%s) ret=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| lv_ret); |
| } |
| assert(lv_ret != -1); |
| if (lv_ret == 0) |
| { |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) EOF received\n", |
| pp_where, FUNCTION, |
| pp_where_detail); |
| return -1; // EOF |
| } |
| if (lv_ret > 0) |
| gv_xmpi_count_read += lv_ret; |
| else |
| { |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) cr=%d, rc=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| gv_xmpi_count_read, |
| gv_xmpi_read_count); |
| } |
| if (gv_xmpi_count_read >= gv_xmpi_read_count) |
| { |
| gv_xmpi_state = XMPI_RSTATE_HDR; |
| lv_cont = true; |
| } |
| break; |
| |
| case XMPI_RSTATE_HDR: |
| assert(gv_xmpi_rd.iv_hdr.ia_sig[0] == XMPI_PMH_SIG0); // TODO |
| assert(gv_xmpi_rd.iv_hdr.ia_sig[1] == XMPI_PMH_SIG1); // TODO |
| assert(gv_xmpi_rd.iv_hdr.ia_sig[2] == XMPI_PMH_SIG2); // TODO |
| assert(gv_xmpi_rd.iv_hdr.ia_sig[3] == XMPI_PMH_SIG3); // TODO |
| gv_xmpi_count_read = 0; |
| gv_xmpi_read_count = 0; |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) hdr, dsize=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| gv_xmpi_rd.iv_hdr.iv_dsize); |
| gv_xmpi_rd.iv_data_len = gv_xmpi_rd.iv_hdr.iv_dsize; |
| if (gv_xmpi_rd.iv_hdr.iv_dsize > 0) |
| { |
| gv_xmpi_rd.ip_data = (char *) pp_buf; |
| gv_xmpi_read_count += gv_xmpi_rd.iv_data_len; |
| } |
| gv_xmpi_state = XMPI_RSTATE_DATA; |
| if (gv_xmpi_read_count == 0) |
| gv_xmpi_state = XMPI_RSTATE_DONE; |
| lv_cont = true; |
| break; |
| |
| case XMPI_RSTATE_DATA: |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) read data, cnt=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| gv_xmpi_rd.iv_data_len - gv_xmpi_count_read); |
| lv_ret = (int) read(pv_sock, |
| &gv_xmpi_rd.ip_data[gv_xmpi_count_read], |
| gv_xmpi_rd.iv_data_len - gv_xmpi_count_read); |
| if (gv_xmpi_trace) |
| { |
| if (lv_ret == -1) |
| printf("%s: %s (%s) errno=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| errno); |
| else |
| printf("%s: %s (%s) ret=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| lv_ret); |
| } |
| assert(lv_ret != -1); |
| if (lv_ret == 0) |
| { |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) EOF received\n", |
| pp_where, FUNCTION, |
| pp_where_detail); |
| return -1; // EOF |
| } |
| if (lv_ret > 0) |
| gv_xmpi_count_read += lv_ret; |
| if (gv_xmpi_count_read >= gv_xmpi_read_count) |
| gv_xmpi_state = XMPI_RSTATE_DONE; |
| lv_cont = true; |
| break; |
| |
| case XMPI_RSTATE_DONE: |
| if (gv_xmpi_trace) |
| { |
| printf("%s: %s (%s) hdr=%p, len=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| (void *) &gv_xmpi_rd.iv_hdr, |
| (int) sizeof(gv_xmpi_rd.iv_hdr)); |
| if (gv_xmpi_rd.iv_data_len > 0) |
| { |
| printf("%s: %s (%s) data=%p, len=%d\n", |
| pp_where, FUNCTION, |
| pp_where_detail, |
| gv_xmpi_rd.ip_data, |
| gv_xmpi_rd.iv_data_len); |
| } |
| } |
| *pp_cnt = gv_xmpi_rd.iv_hdr.iv_dsize; |
| gv_xmpi_state = XMPI_RSTATE_INIT; |
| break; |
| |
| default: |
| assert(0); // WOOPS |
| } |
| } while (lv_cont); |
| return 0; // TODO |
| } |
| |
| static int xmpi_send(const char *pp_where, |
| const char *pp_where_detail, |
| int pv_sock, |
| void *pp_buf, |
| int pv_cnt) |
| { |
| const char *FUNCTION = "xmpi_send"; |
| |
| if (gv_xmpi_trace) |
| { |
| printf("%s: %s (%s) ENTER , sock=%d, buf=%p, cnt=%d\n", |
| pp_where, |
| FUNCTION, |
| pp_where_detail, |
| pv_sock, |
| pp_buf, |
| pv_cnt); |
| } |
| struct iovec la_iovec[2]; |
| XMPI_PMH_Type lv_hdr; |
| lv_hdr.ia_sig[0] = XMPI_PMH_SIG0; |
| lv_hdr.ia_sig[1] = XMPI_PMH_SIG1; |
| lv_hdr.ia_sig[2] = XMPI_PMH_SIG2; |
| lv_hdr.ia_sig[3] = XMPI_PMH_SIG3; |
| lv_hdr.iv_dsize = pv_cnt; |
| la_iovec[0].iov_base = &lv_hdr; |
| la_iovec[0].iov_len = sizeof(lv_hdr); |
| la_iovec[1].iov_base = pp_buf; |
| la_iovec[1].iov_len = pv_cnt; |
| struct msghdr lv_msg; |
| lv_msg.msg_namelen = 0; |
| lv_msg.msg_controllen = 0; |
| lv_msg.msg_flags = 0; |
| lv_msg.msg_iov = la_iovec; |
| lv_msg.msg_iovlen = 2; |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) sendmsg iovlen=%d, iov[0].len=%d, iov[1].len=%d\n", |
| pp_where, |
| FUNCTION, |
| pp_where_detail, |
| (int) lv_msg.msg_iovlen, |
| (int) la_iovec[0].iov_len, |
| (int) la_iovec[1].iov_len); |
| int lv_err = (int) sendmsg(pv_sock, &lv_msg, 0); |
| if (gv_xmpi_trace) |
| printf("%s: %s (%s) sendmsg ret=%d\n", |
| pp_where, |
| FUNCTION, |
| pp_where_detail, |
| lv_err); |
| if (gv_xmpi_trace && (lv_err == -1)) |
| printf("%s: %s (%s) errno=%d\n", |
| pp_where, |
| FUNCTION, |
| pp_where_detail, |
| errno); |
| assert(lv_err != -1); |
| |
| // |
| // If it wasn't all sent, then send the rest |
| // |
| assert(lv_err >= (int) sizeof(lv_hdr)); // the following algorithm depends on this |
| int lv_cnt = (int) (la_iovec[0].iov_len + |
| la_iovec[1].iov_len - |
| lv_err); |
| int lv_off = lv_err - (int) sizeof(lv_hdr); |
| char *lp_buf = (char *) pp_buf; |
| while (lv_cnt > 0) |
| { |
| lv_err = (int) write(pv_sock, &lp_buf[lv_off], lv_cnt); |
| assert(lv_err != -1); |
| lv_cnt -= lv_err; |
| lv_off += lv_err; |
| } |
| lv_err = pv_cnt; |
| return lv_err; |
| } |
| |
| static int xmpi_set_nodelay(const char *pp_where, int pv_sock) |
| { |
| const char *FUNCTION = "xmpi_set_nodelay"; |
| |
| int lv_tcpopt = 1; |
| int lv_err = setsockopt(pv_sock, |
| IPPROTO_TCP, |
| TCP_NODELAY, |
| (char *) &lv_tcpopt, |
| sizeof(lv_tcpopt)); |
| if (gv_xmpi_trace) |
| printf("%s: %s sock=%d, err=%d\n", |
| pp_where, |
| FUNCTION, |
| pv_sock, |
| lv_err); |
| int lv_gtcpopt = 1; |
| socklen_t lv_gtcpoptlen = sizeof(lv_gtcpopt); |
| int lv_gerr = getsockopt(pv_sock, |
| IPPROTO_TCP, |
| TCP_NODELAY, |
| (char *) &lv_gtcpopt, |
| &lv_gtcpoptlen); |
| assert(lv_gerr == 0); |
| assert(lv_gtcpopt != 0); |
| assert(lv_gtcpoptlen == sizeof(lv_gtcpopt)); |
| return lv_err; |
| } |
| |
| static int xmpi_set_reuse(const char *pp_where, int pv_sock) |
| { |
| const char *FUNCTION = "xmpi_set_reuse"; |
| |
| int lv_value = 1; |
| int lv_err = setsockopt(pv_sock, |
| SOL_SOCKET, |
| SO_REUSEADDR, |
| (char *) &lv_value, |
| sizeof(lv_value)); |
| if (gv_xmpi_trace) |
| printf("%s: %s sock=%d, err=%d\n", |
| pp_where, |
| FUNCTION, |
| pv_sock, |
| lv_err); |
| return lv_err; |
| } |
| |
| char *XMPIErrMsg(int err) |
| { |
| static char strBuf[XMPI_STRING_BUF_SIZE] = { 0 }; |
| snprintf( strBuf, sizeof(strBuf), "MPI Error=%d ", err ); |
| return(strBuf); |
| } |
| |
| int XMPI_Close_port(const char *port_name) |
| { |
| const char *WHERE = "XMPI_Close_port"; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER port-name=%s\n", WHERE, port_name); |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Comm_accept(const char *port_name, |
| MPI_Info info, |
| int root, |
| MPI_Comm comm, |
| MPI_Comm *newcomm) |
| { |
| const char *WHERE = "XMPI_Comm_accept"; |
| info = info; |
| root = root; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER port-name=%s, comm=0x%x, newcomm=%p\n", WHERE, port_name, comm, newcomm); |
| |
| struct sockaddr lv_c_addr; |
| socklen_t lv_c_addr_len = sizeof(lv_c_addr); |
| if (gv_xmpi_trace) |
| printf("%s: accept attempt to sock=%d\n", WHERE, gv_xmpi_listen_sock); |
| int lv_sock = accept(gv_xmpi_listen_sock, &lv_c_addr, &lv_c_addr_len); |
| assert(lv_sock != -1); |
| int lv_err = xmpi_set_reuse(WHERE, lv_sock); |
| assert(lv_err == 0); |
| lv_err = xmpi_set_nodelay(WHERE, lv_sock); |
| assert(lv_err == 0); |
| *newcomm = lv_sock | XMPI_COMM_MASK; |
| if (gv_xmpi_trace) |
| printf("%s: EXIT accept completed on sock=%d, new sock=%d\n", |
| WHERE, gv_xmpi_listen_sock, lv_sock); |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Comm_connect(const char *port_name, |
| MPI_Info info, |
| int root, |
| MPI_Comm comm, |
| MPI_Comm *newcomm) |
| { |
| const char *WHERE = "XMPI_Comm_connect"; |
| char la_host[1000]; |
| char la_hostbuf[1000]; |
| const char *lp_colon; |
| int lv_hostenterrno; |
| uint16_t lv_port; |
| info = info; |
| root = root; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER port-name=%s, comm=0x%x, newcomm=%p\n", WHERE, port_name, comm, newcomm); |
| lp_colon = strstr(port_name, ":"); |
| assert(lp_colon != NULL); |
| strcpy(la_host, port_name); |
| int lv_len = lp_colon - port_name; |
| la_host[lv_len] = '\0'; |
| lv_port = atoi(&lp_colon[1]); |
| int lv_sock = socket(AF_INET, SOCK_STREAM, 0); |
| assert(lv_sock != -1); |
| int lv_err = xmpi_set_reuse(WHERE, lv_sock); |
| assert(lv_err == 0); |
| lv_err = xmpi_set_nodelay(WHERE, lv_sock); |
| assert(lv_err == 0); |
| struct sockaddr_in lv_addr; |
| memset(&lv_addr, 0, sizeof(lv_addr)); |
| lv_addr.sin_family = AF_INET; |
| lv_addr.sin_port = htons((uint16_t) lv_port); |
| struct hostent lv_hostent; |
| struct hostent *lp_hostent; |
| lv_err = gethostbyname_r(la_host, |
| &lv_hostent, |
| la_hostbuf, |
| sizeof(la_hostbuf), |
| &lp_hostent, |
| &lv_hostenterrno); |
| assert(lv_err == 0); |
| assert(lp_hostent != NULL); |
| assert(*(long *) lp_hostent->h_addr != -1); |
| lv_addr.sin_addr.s_addr = (uint32_t) *(uint32_t *) lp_hostent->h_addr; |
| if (gv_xmpi_trace) |
| printf("%s: connect attempt to host=%s, port=%d\n", |
| WHERE, la_host, lv_port); |
| lv_err = connect(lv_sock, |
| (struct sockaddr *) &lv_addr, |
| sizeof(struct sockaddr)); |
| if (gv_xmpi_trace) |
| { |
| if (lv_err) |
| printf("%s: connect failure, errno=%d\n", WHERE, errno); |
| else |
| printf("%s: connect completed\n", WHERE); |
| } |
| int lv_ret; |
| if (lv_err == -1) |
| { |
| lv_ret = MPI_ERR_NAME; |
| } |
| else |
| { |
| assert(lv_err != -1); |
| *newcomm = lv_sock | XMPI_COMM_MASK; |
| lv_ret = MPI_SUCCESS; |
| } |
| |
| return lv_ret; |
| } |
| |
| int XMPI_Comm_disconnect(MPI_Comm *comm) |
| { |
| const char *WHERE = "XMPI_Comm_disconnect"; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER comm=%d\n", WHERE, *comm); |
| if ((*comm & XMPI_COMM_MASK) == XMPI_COMM_MASK) |
| { |
| xmpi_chk_valid_comm(*comm); |
| *comm = 0; |
| } |
| else |
| { |
| // ignore |
| } |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Comm_set_errhandler(MPI_Comm comm, |
| MPI_Errhandler errhandler) |
| { |
| const char *WHERE = "XMPI_Comm_set_errhandler"; |
| errhandler = errhandler; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER comm=%d\n", WHERE, comm); |
| xmpi_chk_valid_comm(comm); |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Open_port(MPI_Info info, char *port_name) |
| { |
| const char *WHERE = "XMPI_Open_port"; |
| static char la_host[1000]; |
| char la_hostbuf[1000]; |
| int lv_err; |
| int lv_hostenterrno; |
| uint16_t lv_port; |
| info = info; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER port_name=%p\n", WHERE, port_name); |
| lv_err = gethostname(la_host, sizeof(la_host)); |
| assert(lv_err == 0); |
| int lv_sock = socket(AF_INET, SOCK_STREAM, 0); |
| assert(lv_sock != -1); |
| lv_err = xmpi_set_reuse(WHERE, lv_sock); |
| assert(lv_err == 0); |
| struct sockaddr_in lv_addr; |
| lv_port = 0; |
| memset(&lv_addr, 0, sizeof(lv_addr)); |
| lv_addr.sin_family = AF_INET; |
| lv_addr.sin_port = htons(lv_port); |
| struct hostent lv_hostent; |
| struct hostent *lp_hostent; |
| lv_err = gethostbyname_r(la_host, |
| &lv_hostent, |
| la_hostbuf, |
| sizeof(la_hostbuf), |
| &lp_hostent, |
| &lv_hostenterrno); |
| assert(lv_err == 0); |
| assert(lp_hostent != NULL); |
| bool lv_done = false; |
| for (int lv_inx = 0;; lv_inx++) |
| { |
| long *lp_addr = (long *) lp_hostent->h_addr_list[lv_inx]; |
| if (lp_addr == NULL) |
| break; |
| if (*lp_addr == 0) |
| break; |
| lv_addr.sin_addr.s_addr = (int) *lp_addr; |
| if (gv_xmpi_trace) |
| { |
| unsigned char *lp_addrp = (unsigned char *) lp_addr; |
| printf("%s: trying to bind to host=%d.%d.%d.%d:%d, sock=%d\n", |
| WHERE, lp_addrp[0], lp_addrp[1], |
| lp_addrp[2], lp_addrp[3], lv_port, |
| lv_sock); |
| } |
| lv_err = bind(lv_sock, (struct sockaddr *) &lv_addr, |
| sizeof(struct sockaddr)); |
| if (lv_err == 0) |
| { |
| lv_done = true; |
| break; |
| } else |
| { |
| if (gv_xmpi_trace) |
| printf("%s: bind failed, err=%d, sock=%d, host=%s\n", |
| WHERE, errno, lv_sock, la_host); |
| } |
| } |
| assert(lv_done); |
| lv_err = listen(lv_sock, 1); |
| assert(lv_err != -1); |
| gv_xmpi_listen_sock = lv_sock; |
| socklen_t lv_len = sizeof(lv_addr); |
| lv_err = getsockname(lv_sock, (struct sockaddr *) &lv_addr, &lv_len); |
| assert(lv_err == 0); |
| lv_port = ntohs(lv_addr.sin_port); |
| unsigned char *lp_addrp = (unsigned char *) &lv_addr.sin_addr.s_addr; |
| if (gv_xmpi_trace) |
| { |
| printf("%s: bound to host=%d.%d.%d.%d:%d, sock=%d\n", |
| WHERE, lp_addrp[0], lp_addrp[1], |
| lp_addrp[2], lp_addrp[3], lv_port, |
| lv_sock); |
| } |
| sprintf(port_name, "%d.%d.%d.%d:%d", |
| lp_addrp[0], |
| lp_addrp[1], |
| lp_addrp[2], |
| lp_addrp[3], |
| lv_port); |
| if (gv_xmpi_trace) |
| printf("%s: EXIT OK port_name=%s\n", WHERE, port_name); |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Recv(void *buf, |
| int count, |
| MPI_Datatype datatype, |
| int source, |
| int tag, |
| MPI_Comm comm, |
| MPI_Status *status) |
| { |
| const char *WHERE = "XMPI_Recv"; |
| int recvCount = 0; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER buf=%p, count=%d, comm=0x%x\n", WHERE, buf, count, comm); |
| xmpi_chk_valid_comm(comm); |
| int lv_count; |
| int lv_err = xmpi_recv(WHERE, WHERE, comm & ~XMPI_COMM_MASK, buf, count, &lv_count); |
| int lv_ret; |
| if (lv_err == -1) |
| { |
| lv_ret = MPI_ERR_EXITED; |
| if (gv_xmpi_trace) |
| printf("%s: EXIT EXITED\n", WHERE); |
| } |
| else |
| { |
| assert(lv_err == 0); |
| status->MPI_SOURCE = source; |
| status->MPI_TAG = tag; |
| status->MPI_ERROR = MPI_SUCCESS; |
| switch ( datatype ) |
| { |
| case MPI_CHAR: |
| count = recvCount; |
| break; |
| case MPI_INT: |
| count = recvCount / sizeof(int); |
| break; |
| } |
| status->count = lv_count; |
| lv_ret = MPI_SUCCESS; |
| if (gv_xmpi_trace) |
| printf("%s: EXIT OK\n", WHERE); |
| } |
| return lv_ret; |
| } |
| |
| int XMPI_Send(const void *buf, |
| int count, |
| MPI_Datatype datatype, |
| int dest, |
| int tag, |
| MPI_Comm comm) |
| { |
| const char *WHERE = "XMPI_Send"; |
| int sendCount; |
| dest = dest; |
| tag = tag; |
| |
| switch ( datatype ) |
| { |
| case MPI_CHAR: |
| sendCount = count; |
| break; |
| case MPI_INT: |
| sendCount = count * sizeof(int); |
| break; |
| } |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER buf=%p, count=%d, sendCount=%d, comm=0x%x\n", |
| WHERE, buf, count, sendCount, comm); |
| xmpi_chk_valid_comm(comm); |
| int lv_err = xmpi_send(WHERE, WHERE, comm & ~XMPI_COMM_MASK, (void *) buf, sendCount); |
| assert(lv_err == sendCount); |
| if (gv_xmpi_trace) |
| printf("%s: EXIT OK\n", WHERE); |
| return MPI_SUCCESS; |
| } |
| |
| int XMPI_Sendrecv(const void *sendbuf, |
| int sendcount, |
| MPI_Datatype sendtype, |
| int dest, |
| int sendtag, |
| void *recvbuf, |
| int recvcount, |
| MPI_Datatype recvtype, |
| int source, |
| int recvtag, |
| MPI_Comm comm, |
| MPI_Status *status) |
| { |
| const char *WHERE = "XMPI_Sendrecv"; |
| source = source; |
| |
| if (gv_xmpi_trace) |
| printf("%s: ENTER sendbuf=%p, sendcount=%d, recvbuf=%p, recvcount=%d, comm=0x%x\n", WHERE, sendbuf, sendcount, recvbuf, recvcount, comm); |
| xmpi_chk_valid_comm(comm); |
| int lv_err = XMPI_Send(sendbuf, |
| sendcount, |
| sendtype, |
| dest, |
| sendtag, |
| comm); |
| assert(lv_err == 0); |
| lv_err = XMPI_Recv(recvbuf, |
| recvcount, |
| recvtype, |
| dest, |
| recvtag, |
| comm, |
| status); |
| int lv_ret; |
| if (lv_err) |
| { |
| lv_ret = MPI_ERR_EXITED; |
| if (gv_xmpi_trace) |
| printf("%s: EXIT EXITED, %s\n", WHERE, XMPIErrMsg(lv_err)); |
| } |
| else |
| { |
| if (gv_xmpi_trace) |
| printf("%s: EXIT OK\n", WHERE); |
| lv_ret = MPI_SUCCESS; |
| } |
| return lv_ret; |
| } |
| |