From 209bbbb6ad4d788160a26b0a4a184bb5a356df28 Mon Sep 17 00:00:00 2001 From: Graham Fagg Date: Wed, 11 Aug 2004 21:07:16 +0000 Subject: [PATCH] Added mca_oob_recv_packed() which is a wrapper for oob_recv that recvs into a buffer that is hander to the user. No lowlevel changes. (This will be used by GPR). Todo: sends (easy) and nb recv (harder) This commit was SVN r2070. --- src/mca/oob/base/base.h | 33 ++++++++++++++++++++- src/mca/oob/base/oob_base_recv.c | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/mca/oob/base/base.h b/src/mca/oob/base/base.h index a39292f505..e5961b42b9 100644 --- a/src/mca/oob/base/base.h +++ b/src/mca/oob/base/base.h @@ -11,6 +11,7 @@ #include "mca/mca.h" #include "mca/ns/ns.h" #include +#include "util/pack.h" /* @@ -62,7 +63,7 @@ typedef enum { * * An example of usage - to determine the size of the next available message w/out receiving it: * -* int size = mca_oob_recv(name, 0, 0, MSG_OOB_PEEK|MSG_OOB_TRUNC); +* int size = mca_oob_recv(name, 0, 0, MCA_OOB_TRUNC|MCA_OOB_PEEK); */ #define MCA_OOB_PEEK 0x01 /**< flag to oob_recv to allow caller to peek a portion of the next available @@ -198,6 +199,31 @@ int mca_oob_recv_ntoh( int tag, int flags); + +/** +* Similiar to unix read(2) +* +* @param peer (IN) Opaque name of peer process or MCA_OOB_NAME_ANY for wildcard receive. +* @param buf (OUT) Array of iovecs describing user buffers and lengths. +* @param tag (IN) User defined tag for matching send/recv. +* @return OMPI error code (<0) on error or number of bytes actually received. +* +* +* This version of oob_recv is as above except it does NOT take a iovec list +* but instead hands back a ompi_buffer_t buffer with the message in it. +* The user is responsible for freeing this buffer with ompi_buffer_free() +* when finished. +* +* +*/ + +int mca_oob_recv_packed ( + ompi_process_name_t* peer, + ompi_buffer_t *buf, + int tag); + + + /* * Non-blocking versions of send/recv. */ @@ -331,6 +357,11 @@ int mca_oob_recv_ntoh_nb( void* cbdata); + + + + + /* * functions for pack and unpack routines */ diff --git a/src/mca/oob/base/oob_base_recv.c b/src/mca/oob/base/oob_base_recv.c index 584b9b98ae..7b44a4d1fa 100644 --- a/src/mca/oob/base/oob_base_recv.c +++ b/src/mca/oob/base/oob_base_recv.c @@ -2,6 +2,8 @@ #include "mca/oob/base/base.h" #include #include +#include "util/pack.h" + /* * Similiar to unix recv(2) @@ -97,3 +99,52 @@ int mca_oob_recv_ntoh( return rc; } +/* +* Similiar to unix recv(2) +* +* @param peer (IN) Opaque name of peer process or MCA_OOB_NAME_ANY for wildcard receive. +* @param buffer (OUT) Buffer that the OOB creates to recv this message... +* @param tag (IN) User defined tag for matching send/recv. +* iovec array without removing the message from the queue. +* @return OMPI error code (<0) on error or number of bytes actually received. +*/ +int mca_oob_recv_packed (ompi_process_name_t* peer, ompi_buffer_t *buf, int tag) +{ + /* ok, this routine is a bit of a cow */ + /* the oob_recv actually needs the real target buffers in advance */ + + /* this forces a three stage method */ + /* first we need to peek the size we will need */ + /* then we allocate a buffer of the correct size and then */ + /* we post a recv with the matching iov :) */ + /* and we hope that someone inbtween has not posted a recv */ + /* that matches. */ + /* To avoid any RACE we NEED to change the OOB lowlevel to */ + /* alloc the buffer for us.. as per original design. */ + /* Or do locking on all recv posting between the peek and recv! GEF */ + + uint32_t insize; + int rc; + struct iovec msg[1]; + ompi_buffer_t tmpbuf; + void *targetptr; + + insize = mca_oob.oob_recv(peer, NULL, 0, tag, MCA_OOB_PEEK|MCA_OOB_TRUNC); + + if (OMPI_ERROR==insize) { return (rc); } + + rc = ompi_buffer_init (&tmpbuf, insize); + if (OMPI_ERROR==rc) { return (rc); } + rc = ompi_buffer_get_ptrs (tmpbuf, &targetptr, NULL, NULL); + if (OMPI_ERROR==rc) { return (rc); } + + /* now update the second IOV */ + msg[0].iov_base = (char*) targetptr; + msg[0].iov_len = insize; + + rc = mca_oob.oob_recv(peer, msg, 1, tag, 0); + + if (OMPI_ERROR!=rc) *buf = tmpbuf; + + return (rc); +}