Blame psm2_mq.h

Packit 961e70
/*
Packit 961e70
Packit 961e70
  This file is provided under a dual BSD/GPLv2 license.  When using or
Packit 961e70
  redistributing this file, you may do so under either license.
Packit 961e70
Packit 961e70
  GPL LICENSE SUMMARY
Packit 961e70
Packit 961e70
  Copyright(c) 2017 Intel Corporation.
Packit 961e70
Packit 961e70
  This program is free software; you can redistribute it and/or modify
Packit 961e70
  it under the terms of version 2 of the GNU General Public License as
Packit 961e70
  published by the Free Software Foundation.
Packit 961e70
Packit 961e70
  This program is distributed in the hope that it will be useful, but
Packit 961e70
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 961e70
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 961e70
  General Public License for more details.
Packit 961e70
Packit 961e70
  Contact Information:
Packit 961e70
  Intel Corporation, www.intel.com
Packit 961e70
Packit 961e70
  BSD LICENSE
Packit 961e70
Packit 961e70
  Copyright(c) 2017 Intel Corporation.
Packit 961e70
Packit 961e70
  Redistribution and use in source and binary forms, with or without
Packit 961e70
  modification, are permitted provided that the following conditions
Packit 961e70
  are met:
Packit 961e70
Packit 961e70
    * Redistributions of source code must retain the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer.
Packit 961e70
    * Redistributions in binary form must reproduce the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer in
Packit 961e70
      the documentation and/or other materials provided with the
Packit 961e70
      distribution.
Packit 961e70
    * Neither the name of Intel Corporation nor the names of its
Packit 961e70
      contributors may be used to endorse or promote products derived
Packit 961e70
      from this software without specific prior written permission.
Packit 961e70
Packit 961e70
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 961e70
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 961e70
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 961e70
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 961e70
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 961e70
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 961e70
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 961e70
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 961e70
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 961e70
Packit 961e70
*/
Packit 961e70
Packit 961e70
#ifndef PSM2_MQ_H
Packit 961e70
#define PSM2_MQ_H
Packit 961e70
Packit 961e70
#include <psm2.h>
Packit 961e70
Packit 961e70
#ifdef __cplusplus
Packit 961e70
extern "C" {
Packit 961e70
#endif
Packit 961e70
Packit 961e70
/*!
Packit 961e70
 * @file psm2_mq.h
Packit 961e70
 * @brief PSM2 Matched Queues
Packit 961e70
 *
Packit 961e70
 * @page psm2_mq Matched Queues interface
Packit 961e70
 *
Packit 961e70
 * The Matched Queues (MQ) interface implements a queue-based communication
Packit 961e70
 * model with the distinction that queue message consumers use a 3-tuple of
Packit 961e70
 * metadata to match incoming messages against a list of preposted receive
Packit 961e70
 * buffers.  These semantics are consistent with those presented by MPI-1.2
Packit 961e70
 * and all the features and side-effects of Message-Passing find their way into
Packit 961e70
 * Matched Queues. There is currently a single MQ context,
Packit 961e70
 * If need be, MQs may expose a function to allocate more than
Packit 961e70
 * one MQ context in the future.  Since an MQ is implicitly bound to a locally
Packit 961e70
 * opened endpoint, handle all MQ functions use an MQ handle instead of an EP
Packit 961e70
 * handle as a communication context.
Packit 961e70
 *
Packit 961e70
 * @section tagmatch MQ Tag Matching
Packit 961e70
 *
Packit 961e70
 * A successful MQ tag match requires an endpoint address (@ref psm2_epaddr_t)
Packit 961e70
 * and a 3-tuple of tag objects.  Two of the tag objects are provided by the
Packit 961e70
 * receiver when posting a receive buffer (@ref psm2_mq_irecv) and the last is
Packit 961e70
 * provided by the sender as part of every message sent (@ref psm2_mq_send and
Packit 961e70
 * @ref psm2_mq_isend).  Since MQ is a receiver-directed communication model,
Packit 961e70
 * the tag matching done at the receiver involves matching the sent message's
Packit 961e70
 * origin and send tag (@c stag) with the source endpointer address, tag (@c
Packit 961e70
 * rtag), and tag selector (@c rtagsel) attached to every preposted receive
Packit 961e70
 * buffer.  The incoming @c stag is compared to the posted @c rtag but only for
Packit 961e70
 * significant bits set to @c 1 in the @c rtagsel.  The @c rtagsel can be used
Packit 961e70
 * to mask off parts (or even all) of the bitwise comparison between sender and
Packit 961e70
 * receiver tags.  A successful match causes the message to be received into
Packit 961e70
 * the buffer with which the tag is matched.  If the incoming message is too
Packit 961e70
 * large, it is truncated to the size of the posted receive buffer.  The
Packit 961e70
 * bitwise operation corresponding to a successful match and receipt of an
Packit 961e70
 * expected message amounts to the following expression evaluating as true:
Packit 961e70
 *
Packit 961e70
 *      @verbatim ((stag ^ rtag) & rtagsel) == 0 @endverbatim
Packit 961e70
 *
Packit 961e70
 * It is up to the user to encode (pack) into the 64-bit unsigned
Packit 961e70
 * integers, including employing the @c rtagsel tag selector as a method to
Packit 961e70
 * wildcart part or all of the bits significant in the tag matching operation.
Packit 961e70
 * For example, MPI uses triple based on context (MPI communicator), source
Packit 961e70
 * rank, send tag. The following code example shows how the triple can be
Packit 961e70
 * packed into 64 bits:
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
 	//
Packit 961e70
 	// 64-bit send tag formed by packing the triple:
Packit 961e70
 	//
Packit 961e70
 	// ( context_id_16bits | source_rank_16bits | send_tag_32bits )
Packit 961e70
 	//
Packit 961e70
 	stag = ( (((context_id)&0xffffULL)<<48)|    \
Packit 961e70
 	         (((source_rank)&0xffffULL)<<32)|   \
Packit 961e70
 	         (((send_tag)&0xffffffffULL)) );
Packit 961e70
   @endcode
Packit 961e70
 *
Packit 961e70
 * Similarly, the receiver applies the @c rtag matching bits and @c rtagsel
Packit 961e70
 * masking bits against a list of send tags and returns the first successful
Packit 961e70
 * match.  Zero bits in the @c tagsel can be used to indicate wildcarded bits
Packit 961e70
 * in the 64-bit tag which can be useful for implementing MPI's
Packit 961e70
 * @c MPI_ANY_SOURCE and @c MPI_ANY_TAG.  Following the example bit splicing in
Packit 961e70
 * the above @c stag example:
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
   	// Example MPI implementation where MPI_COMM_WORLD implemented as 0x3333
Packit 961e70
  
Packit 961e70
   	// MPI_Irecv source_rank=MPI_ANY_SOURCE, tag=7, comm=MPI_COMM_WORLD
Packit 961e70
   	rtag    = 0x3333000000000007;
Packit 961e70
   	rtagsel = 0xffff0000ffffffff;
Packit 961e70
  
Packit 961e70
   	// MPI_Irecv source_rank=3, tag=MPI_ANY_TAG, comm=MPI_COMM_WORLD
Packit 961e70
   	rtag    = 0x3333000300000000;
Packit 961e70
   	rtagsel = 0xffffffff80000000; // can't ignore sign bit in tag
Packit 961e70
  
Packit 961e70
   	// MPI_Irecv source_rank=MPI_ANY_SOURCE, tag=MPI_ANY_TAG, comm=MPI_COMM_WORLD
Packit 961e70
   	rtag    = 0x3333000300000000;
Packit 961e70
   	rtagsel = 0xffff000080000000; // can't ignore sign bit in tag
Packit 961e70
   @endcode
Packit 961e70
 *
Packit 961e70
 *
Packit 961e70
 * Applications that do not follow tag matching semantics can simply always
Packit 961e70
 * pass a value of @c 0 for @c rtagsel, which will always yield a successful
Packit 961e70
 * match to the first preposted buffer.  If a message cannot be matched to any
Packit 961e70
 * of the preposted buffers, the message is delivered as an unexpected
Packit 961e70
 * message.
Packit 961e70
 *
Packit 961e70
 * @section mq_receive MQ Message Reception
Packit 961e70
 *
Packit 961e70
 * MQ messages are either received as @e expected or @e unexpected: @li The
Packit 961e70
 * received message is @e expected if the incoming message tag matches the
Packit 961e70
 * combination of tag and tag selector of at least one of the user-provided
Packit 961e70
 * receive buffers preposted with @ref psm2_mq_irecv.
Packit 961e70
 *
Packit 961e70
 * @li The received message is @e unexpected if the incoming message tag @b
Packit 961e70
 * doesn't match any combination of tag and tag selector from all the
Packit 961e70
 * user-provided receive buffers preposted with @ref psm2_mq_irecv.
Packit 961e70
 *
Packit 961e70
 * Unexpected messages are messages that the MQ library buffers until the
Packit 961e70
 * user provides a receive buffer that can match the unexpected message.
Packit 961e70
 * With Matched Queues and MPI alike, unexpected messages can occur as a
Packit 961e70
 * side-effect of the programming model, whereby the arrival of messages can be
Packit 961e70
 * slightly out of step with the ordering in which the user
Packit 961e70
 * provides receive buffers.  Unexpected messages can also be triggered by the
Packit 961e70
 * difference between the rate at which a sender produces messages and the rate
Packit 961e70
 * at which a paired receiver can post buffers and hence consume the messages.
Packit 961e70
 *
Packit 961e70
 * In all cases, too many @e unexpected messages will negatively affect
Packit 961e70
 * performance.  Users can employ some of the following mechanisms to reduce
Packit 961e70
 * the effect of added memory allocations and copies that result from
Packit 961e70
 * unexpected messages:
Packit 961e70
 *   @li If and when possible, receive buffers should be posted as early as
Packit 961e70
 *       possible and ideally before calling into the progress engine.
Packit 961e70
 *   @li Use of rendezvous messaging that can be controlled with
Packit 961e70
 *       @ref PSM2_MQ_RNDV_HFI_SZ and @ref PSM2_MQ_RNDV_SHM_SZ options.  These
Packit 961e70
 *       options default to values determined to make effective use of
Packit 961e70
 *       bandwidth and are hence not advisable for all communication message
Packit 961e70
 *       sizes, but rendezvous messages inherently prevent unexpected
Packit 961e70
 *       messages by synchronizing the sender with the receiver beforehand.
Packit 961e70
 *   @li The amount of memory that is allocated to handle unexpected messages
Packit 961e70
 *       can be bounded by adjusting the Global @ref PSM2_MQ_MAX_SYSBUF_MBYTES
Packit 961e70
 *       option.
Packit 961e70
 *   @li MQ statistics, such as the amount of received unexpected messages and
Packit 961e70
 *       the aggregate amount of unexpected bytes are available in the @ref
Packit 961e70
 *       psm2_mq_stats structure.
Packit 961e70
 *
Packit 961e70
 * Whenever a match occurs, whether the message is expected or unexpected, it
Packit 961e70
 * is generally up to the user to ensure that the message is not truncated.
Packit 961e70
 * Message truncation occurs when the size of the preposted buffer is less than
Packit 961e70
 * the size of the incoming matched message.  MQ will correctly handle
Packit 961e70
 * message truncation by always copying the appropriate amount of bytes as to
Packit 961e70
 * not overwrite any data.  While it is valid to send less data than the amount
Packit 961e70
 * of data that has been preposted, messages that are truncated will be marked
Packit 961e70
 * @ref PSM2_MQ_TRUNCATION as part of the error code in the message status
Packit 961e70
 * structure (@ref psm2_mq_status_t or @ref psm2_mq_status2_t).
Packit 961e70
 *
Packit 961e70
 * @section mq_completion MQ Completion Semantics
Packit 961e70
 *
Packit 961e70
 * Message completion in Matched Queues follows local completion semantics.
Packit 961e70
 * When sending an MQ message, it is deemed complete when MQ guarantees that
Packit 961e70
 * the source data has been sent and that the entire input source data memory
Packit 961e70
 * location can be safely overwritten.  As with standard Message-Passing,
Packit 961e70
 * MQ does not make any remote completion guarantees for sends.  MQ does
Packit 961e70
 * however, allow a sender to synchronize with a receiver to send a synchronous
Packit 961e70
 * message which sends a message only after a matching receive buffer has been
Packit 961e70
 * posted by the receiver (@ref PSM2_MQ_FLAG_SENDSYNC).
Packit 961e70
 *
Packit 961e70
 * A receive is deemed complete after it has matched its associated receive
Packit 961e70
 * buffer with an incoming send and that the data from the send has been
Packit 961e70
 * completely delivered to the receive buffer.
Packit 961e70
 *
Packit 961e70
 * @section mq_progress MQ Progress Requirements
Packit 961e70
 *
Packit 961e70
 * Progress on MQs must be @e explicitly ensured by the user for correctness.
Packit 961e70
 * The progress requirement holds even if certain areas of the MQ
Packit 961e70
 * implementation require less network attention than others, or if progress
Packit 961e70
 * may internally be guaranteed through interrupts.  The main polling function,
Packit 961e70
 * @ref psm2_poll, is the most general form of ensuring process on a given
Packit 961e70
 * endpoint.  Calling @ref psm2_poll ensures that progress is made over all the
Packit 961e70
 * MQs and other components instantiated over the endpoint passed to @ref
Packit 961e70
 * psm2_poll.
Packit 961e70
 *
Packit 961e70
 * While @ref psm2_poll is the only way to directly ensure progress, other MQ
Packit 961e70
 * functions will conditionally ensure progres depending on how they are used:
Packit 961e70
 *
Packit 961e70
 * @li @ref psm2_mq_wait employs polling and waits until the request is
Packit 961e70
 * completed.  For blocking communication operations where the caller is
Packit 961e70
 * waiting on a single send or receive to complete, psm2_mq_wait usually
Packit 961e70
 * provides the best responsiveness in terms of latency.
Packit 961e70
 *
Packit 961e70
 * @li @ref psm2_mq_test can test a particular request for completion, but @b
Packit 961e70
 * never directly or indirectly ensures progress as it only tests the
Packit 961e70
 * completion status of a request, nothing more.  See functional documentation
Packit 961e70
 * in @ref psm2_mq_test for a detailed discussion.
Packit 961e70
 *
Packit 961e70
 * @li @ref psm2_mq_ipeek ensures progress if and only if the MQ's completion
Packit 961e70
 * queue is empty and will not ensure progress as long as the completion queue
Packit 961e70
 * is non-empty.  Users that always aggressively process all elements of the MQ
Packit 961e70
 * completion queue as part of their own progress engine will indirectly always
Packit 961e70
 * ensure MQ progress. The ipeek mechanism is the preferred way for
Packit 961e70
 * ensuring progress when many non-blocking requests are in flight since ipeek
Packit 961e70
 * returns requests in the order in which they complete.  Depending on how the
Packit 961e70
 * user initiates and completes communication, this may be preferable to
Packit 961e70
 * calling other progress functions on individual requests.
Packit 961e70
 */
Packit 961e70
Packit 961e70
/*! @defgroup mq PSM Matched Queues
Packit 961e70
 *
Packit 961e70
 * @{
Packit 961e70
 */
Packit 961e70
Packit 961e70
/** @brief Initialize the MQ component for MQ communication
Packit 961e70
 *
Packit 961e70
 * This function provides the Matched Queue handle necessary to perform all
Packit 961e70
 * Matched Queue communication operations.
Packit 961e70
 *
Packit 961e70
 * @param[in] ep Endpoint over which to initialize Matched Queue
Packit Service 7ed5cc
 * @param[in] ignored
Packit 961e70
 * @param[in] opts Set of options for Matched Queue
Packit 961e70
 * @param[in] numopts Number of options passed
Packit 961e70
 * @param[out] mq User-supplied storage to return the Matched Queue handle
Packit 961e70
 *                associated to the newly created Matched Queue.
Packit 961e70
 *
Packit 961e70
 * @remark This function can be called many times to retrieve the MQ handle
Packit 961e70
 *         associated to an endpoint, but options are only considered the first
Packit 961e70
 *         time the function is called.
Packit 961e70
 *
Packit 961e70
 * @post The user obtains a handle to an instantiated Match Queue.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK A new Matched Queue has been instantiated across all the
Packit 961e70
 *         members of the group.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
   	int try_open_endpoint_and_initialize_mq(
Packit 961e70
   	       psm2_ep_t *ep,	// endpoint handle
Packit 961e70
   	       psm2_epid_t *epid, // unique endpoint ID
Packit 961e70
   	       psm2_uuid_t job_uuid, // unique job uuid, for ep_open
Packit 961e70
   	       psm2_mq_t *mq, // MQ handle initialized on endpoint 'ep'
Packit 961e70
   	       uint64_t communicator_bits) // Where we store our communicator or
Packit 961e70
   	                                   // context bits in the 64-bit tag.
Packit 961e70
   	{
Packit 961e70
   	    // Simplified open, see psm2_ep_open documentation for more info
Packit 961e70
   	    psm2_ep_open(job_uuid,
Packit 961e70
   	                NULL, // no options
Packit 961e70
   	                ep, epid);
Packit 961e70
Packit 961e70
   	    // We initialize a matched queue by telling PSM the bits that are
Packit 961e70
   	    // order-significant in the tag.  Point-to-point ordering will not be
Packit 961e70
   	    // maintained between senders where the communicator bits are not the
Packit 961e70
   	    // same.
Packit 961e70
   	    psm2_mq_init(ep,
Packit 961e70
   	                communicator_bits,
Packit 961e70
   	                NULL, // no other MQ options
Packit 961e70
   	                0,    // 0 options passed
Packit 961e70
   	                mq);  // newly initialized matched Queue
Packit 961e70
Packit 961e70
   	    return 1;
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit Service 7ed5cc
psm2_mq_init(psm2_ep_t ep, uint64_t ignored,
Packit 961e70
	    const struct psm2_optkey *opts, int numopts, psm2_mq_t *mq);
Packit 961e70
Packit 961e70
#define PSM2_MQ_ORDERMASK_NONE	0ULL
Packit 961e70
	/**< This macro is reserved for future tag order masking support. */
Packit 961e70
Packit 961e70
#define PSM2_MQ_ORDERMASK_ALL	0xffffffffffffffffULL
Packit 961e70
	/**< This macro is reserved for future tag order masking support. */
Packit 961e70
Packit 961e70
/** @brief Finalize (close) an MQ handle
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK A given Matched Queue has been freed and use of the future
Packit 961e70
 * use of the handle produces undefined results.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_finalize(psm2_mq_t mq);
Packit 961e70
Packit 961e70
#define PSM2_MQ_TAG_ELEMENTS 4
Packit 961e70
	/**< Represents the number of 32-bit tag elements in the psm2_mq_tag_t
Packit 961e70
	 *   type plus one extra element to keep alignment and padding
Packit 961e70
	 *   as 16 bytes.  */
Packit 961e70
Packit 961e70
/** @struct psm2_mq_tag
Packit 961e70
 ** @brief MQ Message tag
Packit 961e70
 *
Packit 961e70
 * Extended message tag type introduced in PSM 2.0.  The previous 64 bit tag
Packit 961e70
 * values are replaced by a struct containing three 32 bit tag values for a
Packit 961e70
 * total of 96 bits.  Matching semantics are unchanged from the previous 64-bit
Packit 961e70
 * matching scheme; the only difference is that 96 bits are matched instead of
Packit 961e70
 * 64.  For interoperability with existing PSM routines, 64 bit tags are
Packit 961e70
 * extended to a 96 bit tag by setting the upper 32 bits (tag[2] or tag2) to
Packit 961e70
 * zero.  Other than this caveat, all of the existing routines using 64-bit
Packit 961e70
 * tags are interchangeable with PSM2 routines using this psm2_mq_tag_t type.
Packit 961e70
 * For example, a message sent using @ref psm2_mq_send can be received using
Packit 961e70
 * @ref psm2_mq_irecv2, provided the tags match as described above.
Packit 961e70
 */
Packit 961e70
typedef
Packit 961e70
//struct psm2_mq_tag {
Packit 961e70
union psm2_mq_tag {
Packit 961e70
//    union {
Packit 961e70
		uint32_t tag[PSM2_MQ_TAG_ELEMENTS]; /* No longer specifying
Packit 961e70
						     * alignment as it makes
Packit 961e70
						     * code break with newer
Packit 961e70
						     * compilers. */
Packit 961e70
Packit 961e70
            /**< 3 x 32bit array representation of @ref psm2_mq_tag */
Packit 961e70
		struct {
Packit 961e70
			uint32_t tag0; /**< 1 of 3 uint32_t tag values */
Packit 961e70
			uint32_t tag1; /**< 2 of 3 uint32_t tag values */
Packit 961e70
			uint32_t tag2; /**< 3 of 3 uint32_t tag values */
Packit 961e70
		};
Packit 961e70
//	};
Packit 961e70
} psm2_mq_tag_t;
Packit 961e70
Packit 961e70
/** @brief MQ Non-blocking operation status
Packit 961e70
 *
Packit 961e70
 * Message completion status for asynchronous communication operations.
Packit 961e70
 * For wait and test functions, MQ fills in the structure upon completion.
Packit 961e70
 * Upon completion, receive requests fill in every field of the status
Packit 961e70
 * structure while send requests only return a valid error_code and context
Packit 961e70
 * pointer.
Packit 961e70
 */
Packit 961e70
typedef
Packit 961e70
struct psm2_mq_status {
Packit 961e70
	/** Sender's original message tag (receive reqs only) */
Packit 961e70
	uint64_t msg_tag;
Packit 961e70
	/** Sender's original message length (receive reqs only) */
Packit 961e70
	uint32_t msg_length;
Packit 961e70
	/** Actual number of bytes transfered (receive reqs only) */
Packit 961e70
	uint32_t nbytes;
Packit 961e70
	/** MQ error code for communication operation */
Packit 961e70
	psm2_error_t error_code;
Packit 961e70
	/**< User-associated context for send or receive */
Packit 961e70
	void *context;
Packit 961e70
} psm2_mq_status_t;
Packit 961e70
Packit 961e70
/** @brief MQ Non-blocking operation status
Packit 961e70
 *
Packit 961e70
 * Message completion status for asynchronous communication operations.  For
Packit 961e70
 * wait and test functions, MQ fills in the structure upon completion.  Upon
Packit 961e70
 * completion, requests fill in every field of the status structure with the
Packit 961e70
 * exception of the nbytes field, which is only valid for receives.  Version 2
Packit 961e70
 * of the status type contains an @ref psm2_mq_tag_t type to represent the tag
Packit 961e70
 * instead of a 64-bit integer value and is for use with PSM v2 routines.
Packit 961e70
 */
Packit 961e70
Packit 961e70
typedef
Packit 961e70
struct psm2_mq_status2 {
Packit 961e70
	/** Remote peer's epaddr */
Packit 961e70
	psm2_epaddr_t msg_peer;
Packit 961e70
	/** Sender's original message tag */
Packit 961e70
	psm2_mq_tag_t msg_tag __attribute__ ((aligned(16)));/* Alignment added
Packit 961e70
							     * to preserve the
Packit 961e70
							     * layout as is
Packit 961e70
							     * expected by
Packit 961e70
							     * existent code */
Packit 961e70
	/** Sender's original message length */
Packit 961e70
	uint32_t msg_length;
Packit 961e70
	/** Actual number of bytes transfered (receiver only) */
Packit 961e70
	uint32_t nbytes;
Packit 961e70
	/** MQ error code for communication operation */
Packit 961e70
	psm2_error_t error_code;
Packit 961e70
	/** User-associated context for send or receive */
Packit 961e70
	void *context;
Packit 961e70
} psm2_mq_status2_t;
Packit 961e70
Packit 961e70
/** @brief PSM2 Communication handle (opaque) */
Packit 961e70
typedef struct psm2_mq_req *psm2_mq_req_t;
Packit 961e70
Packit 961e70
Packit 961e70
/** @brief MQ Request Struct
Packit 961e70
 *
Packit 961e70
 * Message completion request for asynchronous communication operations.
Packit 961e70
 * Upon completion, requests are filled with the valid data for the
Packit 961e70
 * corresponding send/recv operation that was completed. This datatype
Packit 961e70
 * contains the status data and is converted into the
Packit 961e70
 * mq_status structures in wait/test functions.
Packit 961e70
 */
Packit 961e70
struct psm2_mq_req_user {
Packit 961e70
	/* Tag matching vars */
Packit 961e70
	psm2_epaddr_t peer;
Packit 961e70
	psm2_mq_tag_t tag __attribute__ ((aligned(16)));/* Alignment added
Packit 961e70
							 * to preserve the
Packit 961e70
							 * layout as is
Packit 961e70
							 * expected by
Packit 961e70
							 * existent code */
Packit 961e70
	psm2_mq_tag_t tagsel;	/* used for receives */
Packit 961e70
Packit 961e70
	/* Buffer attached to request.  May be a system buffer for unexpected
Packit 961e70
	 * messages or a user buffer when an expected message */
Packit 961e70
	uint8_t *buf;
Packit 961e70
	uint32_t buf_len;
Packit 961e70
	uint32_t error_code;
Packit 961e70
Packit 961e70
	uint32_t recv_msglen;	/* Message length we are ready to receive */
Packit 961e70
	uint32_t send_msglen;	/* Message length from sender */
Packit 961e70
Packit 961e70
	/* Used for request to send messages */
Packit 961e70
	void *context;		/* user context associated to sends or receives */
Packit 961e70
Packit 961e70
	uint64_t user_reserved[4];
Packit 961e70
};
Packit 961e70
Packit 961e70
/*! @} */
Packit 961e70
/*! @ingroup mq
Packit 961e70
 * @defgroup mq_options PSM Matched Queue Options
Packit 961e70
 * @{
Packit 961e70
 *
Packit 961e70
 * MQ options can be modified at any point at runtime, unless otherwise noted.
Packit 961e70
 * The following example shows how to retrieve the current message size at
Packit 961e70
 * which messages are sent as synchronous.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
   	uint32_t get_hfirv_size(psm2_mq_t mq)
Packit 961e70
   	{
Packit 961e70
   	    uint32_t rvsize;
Packit 961e70
   	    psm2_getopt(mq, PSM2_MQ_RNDV_HFI_SZ, &rvsize);
Packit 961e70
   	    return rvsize;
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
Packit 961e70
/** @brief Get an MQ option (Deprecated. Use psm2_getopt with PSM2_COMPONENT_MQ)
Packit 961e70
 *
Packit 961e70
 * Function to retrieve the value of an MQ option.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue handle
Packit 961e70
 * @param[in] option Index of option to retrieve.  Possible values are:
Packit 961e70
 *            @li @ref PSM2_MQ_RNDV_HFI_SZ
Packit 961e70
 *            @li @ref PSM2_MQ_RNDV_SHM_SZ
Packit 961e70
 *            @li @ref PSM2_MQ_MAX_SYSBUF_MBYTES
Packit 961e70
 *
Packit 961e70
 * @param[in] value Pointer to storage that can be used to store the value of
Packit 961e70
 *            the option to be set.  It is up to the user to ensure that the
Packit 961e70
 *            pointer points to a memory location large enough to accommodate
Packit 961e70
 *            the value associated to the type.  Each option documents the size
Packit 961e70
 *            associated to its value.
Packit 961e70
 *
Packit 961e70
 * @returns PSM2_OK if option could be retrieved.
Packit 961e70
 * @returns PSM2_PARAM_ERR if the option is not a valid option number
Packit 961e70
 */
Packit 961e70
psm2_error_t psm2_mq_getopt(psm2_mq_t mq, int option, void *value);
Packit 961e70
Packit 961e70
/** @brief Set an MQ option (Deprecated. Use psm2_setopt with PSM2_COMPONENT_MQ)
Packit 961e70
 *
Packit 961e70
 * Function to set the value of an MQ option.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue handle
Packit 961e70
 * @param[in] option Index of option to retrieve.  Possible values are:
Packit 961e70
 *            @li @ref PSM2_MQ_RNDV_HFI_SZ
Packit 961e70
 *            @li @ref PSM2_MQ_RNDV_SHM_SZ
Packit 961e70
 *            @li @ref PSM2_MQ_MAX_SYSBUF_MBYTES
Packit 961e70
 *
Packit 961e70
 * @param[in] value Pointer to storage that contains the value to be updated
Packit 961e70
 *                  for the supplied option number.  It is up to the user to
Packit 961e70
 *                  ensure that the pointer points to a memory location with a
Packit 961e70
 *                  correct size.
Packit 961e70
 *
Packit 961e70
 * @returns PSM2_OK if option could be retrieved.
Packit 961e70
 * @returns PSM2_PARAM_ERR if the option is not a valid option number
Packit 961e70
 * @returns PSM2_OPT_READONLY if the option to be set is a read-only option
Packit 961e70
 *                           (currently no MQ options are read-only).
Packit 961e70
 */
Packit 961e70
psm2_error_t psm2_mq_setopt(psm2_mq_t mq, int option, const void *value);
Packit 961e70
Packit 961e70
/*! @}  */
Packit 961e70
/*! @ingroup mq
Packit 961e70
 * @{
Packit 961e70
 */
Packit 961e70
Packit 961e70
#define PSM2_MQ_FLAG_SENDSYNC	0x01
Packit 961e70
				/**< MQ Send Force synchronous send */
Packit 961e70
Packit 961e70
#define PSM2_MQ_REQINVALID	((psm2_mq_req_t)(NULL))
Packit 961e70
				/**< MQ request completion value */
Packit 961e70
Packit 961e70
#define PSM2_MQ_ANY_ADDR		((psm2_epaddr_t)NULL)
Packit 961e70
				/**< MQ receive from any source epaddr */
Packit 961e70
Packit 961e70
Packit 961e70
/** @brief MQ fast-path operation enumeration
Packit 961e70
 *
Packit 961e70
 * To provide for quick enqueing of send/receives from within an AM handler
Packit 961e70
 * PSM2 provdes fast path send/recv options that will enqueue those ops
Packit 961e70
 * into the MQ. The supported operations to call in fast path are enumerated
Packit 961e70
 * in the @ref psm2_mq_fp_op enum.
Packit 961e70
 */
Packit 961e70
enum psm2_mq_fp_op {
Packit 961e70
	PSM2_MQ_ISEND_FP = 1,
Packit 961e70
	PSM2_MQ_IRECV_FP,
Packit 961e70
};
Packit 961e70
Packit 961e70
/** @brief Post a fast-path isend/irecv into the MQ
Packit 961e70
 *
Packit 961e70
 * Function to only enqueue fast-path non-blocking sends or non-blocking recvs
Packit 961e70
 * into a particular MQ. These calls only work if the process already holds
Packit 961e70
 * the mq progress lock, this case traditionally only applies to calls from
Packit 961e70
 * a registered AM Handler.
Packit 961e70
 *
Packit 961e70
 * This function helps to enable one-sided communication models from middleware
Packit 961e70
 * such as OFI to provide fast >2KB message transfers for RMA operations.
Packit 961e70
 *
Packit 961e70
 * When posting irecvs every MQ message received on a particular MQ,
Packit 961e70
 * the @c tag and @c tagsel parameters are used against the incoming
Packit 961e70
 * message's send tag as described in @ref tagmatch.
Packit 961e70
 *
Packit 961e70
 * When posting isends the user gurantees that the source data will remain
Packit 961e70
 * unmodified until the send is locally completed through a call such as
Packit 961e70
 * @ref psm2_mq_wait or @ref psm2_mq_test.
Packit 961e70
 *
Packit 961e70
 * Progress on the operations enqueued into the MQ will may not occur until
Packit 961e70
 * the next PSM2 progress API is invoked.
Packit 961e70
 *
Packit 961e70
 * @param[in] ep PSM2 endpoint
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] addr Destination EP address (used only on isends)
Packit 961e70
 * @param[in] tag Send/Receive tag
Packit 961e70
 * @param[in] tagsel Receive tag selector (used only on irecvs)
Packit 961e70
 * @param[in] flags Send/Receive Flags
Packit 961e70
 * @param[in] buf Send/Receive buffer
Packit 961e70
 * @param[in] len Send/Receive buffer length
Packit 961e70
 * @param[in] context User context pointer, available in @ref psm2_mq_status_t
Packit 961e70
 *                    upon completion
Packit 961e70
 * @param[in] fp_type Fast-path op requested
Packit 961e70
 * @param[out] req PSM MQ Request handle created by the preposted receive, to
Packit 961e70
 *                 be used for explicitly controlling message receive
Packit 961e70
 *                 completion.
Packit 961e70
 *
Packit 961e70
 * @post The supplied buffer is given to MQ to match against incoming
Packit 961e70
 *       messages unless it is cancelled via @ref psm2_mq_cancel @e before any
Packit 961e70
 *       match occurs.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The receive buffer has successfully been posted to the MQ.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_fp_msg(psm2_ep_t ep, psm2_mq_t mq, psm2_epaddr_t addr, psm2_mq_tag_t *tag,
Packit 961e70
		psm2_mq_tag_t *tagsel, uint32_t flags, void *buf, uint32_t len,
Packit 961e70
		void *context, enum psm2_mq_fp_op fp_type, psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Post a receive to a Matched Queue with tag selection criteria
Packit 961e70
 *
Packit 961e70
 * Function to receive a non-blocking MQ message by providing a preposted
Packit 961e70
 * buffer. For every MQ message received on a particular MQ, the @c tag and @c
Packit 961e70
 * tagsel parameters are used against the incoming message's send tag as
Packit 961e70
 * described in @ref tagmatch.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] rtag Receive tag
Packit 961e70
 * @param[in] rtagsel Receive tag selector
Packit 961e70
 * @param[in] flags Receive flags (None currently supported)
Packit 961e70
 * @param[in] buf Receive buffer
Packit 961e70
 * @param[in] len Receive buffer length
Packit 961e70
 * @param[in] context User context pointer, available in @ref psm2_mq_status_t
Packit 961e70
 *                    upon completion
Packit 961e70
 * @param[out] req PSM MQ Request handle created by the preposted receive, to
Packit 961e70
 *                 be used for explicitly controlling message receive
Packit 961e70
 *                 completion.
Packit 961e70
 *
Packit 961e70
 * @post The supplied receive buffer is given to MQ to match against incoming
Packit 961e70
 *       messages unless it is cancelled via @ref psm2_mq_cancel @e before any
Packit 961e70
 *       match occurs.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The receive buffer has successfully been posted to the MQ.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_irecv(psm2_mq_t mq, uint64_t rtag, uint64_t rtagsel, uint32_t flags,
Packit 961e70
	     void *buf, uint32_t len, void *context, psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Post a receive to a Matched Queue with source and tag selection
Packit 961e70
 *  criteria
Packit 961e70
 *
Packit 961e70
 * Function to receive a non-blocking MQ message by providing a preposted
Packit 961e70
 * buffer. For every MQ message received on a particular MQ, the @c src, @c tag
Packit 961e70
 * and @c tagsel parameters are used against the incoming message's send tag as
Packit 961e70
 * described in @ref tagmatch.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] src Source (sender's) epaddr (may be PSM2_MQ_ANY_ADDR)
Packit 961e70
 * @param[in] rtag Receive tag
Packit 961e70
 * @param[in] rtagsel Receive tag selector
Packit 961e70
 * @param[in] flags Receive flags (None currently supported)
Packit 961e70
 * @param[in] buf Receive buffer
Packit 961e70
 * @param[in] len Receive buffer length
Packit 961e70
 * @param[in] context User context pointer, available in @ref psm2_mq_status2_t
Packit 961e70
 *                    upon completion
Packit 961e70
 * @param[out] req PSM MQ Request handle created by the preposted receive, to
Packit 961e70
 *                 be used for explicitly controlling message receive
Packit 961e70
 *                 completion.
Packit 961e70
 *
Packit 961e70
 * @post The supplied receive buffer is given to MQ to match against incoming
Packit 961e70
 *       messages unless it is cancelled via @ref psm2_mq_cancel @e before any
Packit 961e70
 *       match occurs.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The receive buffer has successfully been posted to the MQ.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_irecv2(psm2_mq_t mq, psm2_epaddr_t src, psm2_mq_tag_t *rtag,
Packit 961e70
	      psm2_mq_tag_t *rtagsel, uint32_t flags, void *buf, uint32_t len,
Packit 961e70
	      void *context, psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Post a receive to a Matched Queue with matched request
Packit 961e70
 *
Packit 961e70
 * Function to receive a non-blocking MQ message by providing a preposted
Packit 961e70
 * buffer. The provided request should already be matched using the @ref
Packit 961e70
 * psm2_mq_improbe or @ref psm2_mq_improbe2 routines.  It is an error to pass a
Packit 961e70
 * request that has not already been matched by one of those routines.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] flags Receive flags (None currently supported)
Packit 961e70
 * @param[in] buf Receive buffer
Packit 961e70
 * @param[in] len Receive buffer length
Packit 961e70
 * @param[in] context User context pointer, available in @ref psm2_mq_status_t
Packit 961e70
 *                    upon completion
Packit 961e70
 * @param[inout] reqo PSM MQ Request handle matched previously by a matched
Packit 961e70
 *		     probe routine (@ref psm2_mq_improbe or @ref
Packit 961e70
 *		     psm2_mq_improbe2), also to be used for explicitly
Packit 961e70
 *		     controlling message receive completion.
Packit 961e70
 *
Packit 961e70
 * @post The supplied receive buffer is given to MQ to deliver the matched
Packit 961e70
 *       message.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The receive buffer has successfully been posted to the MQ.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_imrecv(psm2_mq_t mq, uint32_t flags, void *buf, uint32_t len,
Packit 961e70
	      void *context, psm2_mq_req_t *reqo);
Packit 961e70
Packit 961e70
/** @brief Send a blocking MQ message
Packit 961e70
 *
Packit 961e70
 * Function to send a blocking MQ message, whereby the message is locally
Packit 961e70
 * complete and the source data can be modified upon return.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] dest Destination EP address
Packit 961e70
 * @param[in] flags Message flags, currently:
Packit 961e70
 *            @li PSM2_MQ_FLAG_SENDSYNC tells PSM to send the message
Packit 961e70
 *            synchronously, meaning that the message will not be sent until
Packit 961e70
 *            the receiver acknowledges that it has matched the send with a
Packit 961e70
 *            receive buffer.
Packit 961e70
 * @param[in] stag Message Send Tag
Packit 961e70
 * @param[in] buf Source buffer pointer
Packit 961e70
 * @param[in] len Length of message starting at @c buf.
Packit 961e70
 *
Packit 961e70
 * @post The source buffer is reusable and the send is locally complete.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * @note This send function has been implemented to best suit MPI_Send.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The message has been successfully sent.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_send(psm2_mq_t mq, psm2_epaddr_t dest, uint32_t flags, uint64_t stag,
Packit 961e70
	    const void *buf, uint32_t len);
Packit 961e70
Packit 961e70
/** @brief Send a blocking MQ message
Packit 961e70
 *
Packit 961e70
 * Function to send a blocking MQ message, whereby the message is locally
Packit 961e70
 * complete and the source data can be modified upon return.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] dest Destination EP address
Packit 961e70
 * @param[in] flags Message flags, currently:
Packit 961e70
 *            @li PSM2_MQ_FLAG_SENDSYNC tells PSM to send the message
Packit 961e70
 *            synchronously, meaning that the message will not be sent until
Packit 961e70
 *            the receiver acknowledges that it has matched the send with a
Packit 961e70
 *            receive buffer.
Packit 961e70
 * @param[in] stag Message Send Tag
Packit 961e70
 * @param[in] buf Source buffer pointer
Packit 961e70
 * @param[in] len Length of message starting at @c buf.
Packit 961e70
 *
Packit 961e70
 * @post The source buffer is reusable and the send is locally complete.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * @note This send function has been implemented to best suit MPI_Send.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The message has been successfully sent.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_send2(psm2_mq_t mq, psm2_epaddr_t dest, uint32_t flags,
Packit 961e70
	     psm2_mq_tag_t *stag, const void *buf, uint32_t len);
Packit 961e70
Packit 961e70
/** @brief Send a non-blocking MQ message
Packit 961e70
 *
Packit 961e70
 * Function to initiate the send of a non-blocking MQ message, whereby the
Packit 961e70
 * user guarantees that the source data will remain unmodified until the send
Packit 961e70
 * is locally completed through a call such as @ref psm2_mq_wait or @ref
Packit 961e70
 * psm2_mq_test.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] dest Destination EP address
Packit 961e70
 * @param[in] flags Message flags, currently:
Packit 961e70
 *            @li PSM2_MQ_FLAG_SENDSYNC tells PSM to send the message
Packit 961e70
 *            synchronously, meaning that the message will not be sent until
Packit 961e70
 *            the receiver acknowledges that it has matched the send with a
Packit 961e70
 *            receive buffer.
Packit 961e70
 * @param[in] stag Message Send Tag
Packit 961e70
 * @param[in] buf Source buffer pointer
Packit 961e70
 * @param[in] len Length of message starting at @c buf.
Packit 961e70
 * @param[in] context Optional user-provided pointer available in @ref
Packit 961e70
 *                    psm2_mq_status_t when the send is locally completed.
Packit 961e70
 * @param[out] req PSM MQ Request handle created by the non-blocking send, to
Packit 961e70
 *                 be used for explicitly controlling message completion.
Packit 961e70
 *
Packit 961e70
 * @post The source buffer is not reusable and the send is not locally complete
Packit 961e70
 *       until its request is completed by either @ref psm2_mq_test or @ref
Packit 961e70
 *       psm2_mq_wait.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * @note This send function has been implemented to suit MPI_Isend.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The message has been successfully initiated.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
   	psm2_mq_req_t
Packit 961e70
   	non_blocking_send(const psm2_mq_t mq, psm2_epaddr_t dest_ep,
Packit 961e70
   	                      const void *buf, uint32_t len,
Packit 961e70
   	     		 int context_id, int send_tag, const my_request_t *req)
Packit 961e70
   	{
Packit 961e70
   	    psm2_mq_req_t req_mq;
Packit 961e70
   	    // Set up our send tag, assume that "my_rank" is global and represents
Packit 961e70
   	    // the rank of this process in the job
Packit 961e70
   	    uint64_t tag = ( ((context_id & 0xffff) << 48) |
Packit 961e70
   	                     ((my_rank & 0xffff) << 32)    |
Packit 961e70
   	                     ((send_tag & 0xffffffff)) );
Packit 961e70
  
Packit 961e70
   	    psm2_mq_isend(mq, dest_ep,
Packit 961e70
   	                 0, // no flags
Packit 961e70
   	                 tag,
Packit 961e70
   	                 buf,
Packit 961e70
   	                 len,
Packit 961e70
   	                 req, // this req is available in psm2_mq_status_t when one
Packit 961e70
   	                      // of the synchronization functions is called.
Packit 961e70
   	                 &req_mq);
Packit 961e70
   	    return req_mq;
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_isend(psm2_mq_t mq, psm2_epaddr_t dest, uint32_t flags, uint64_t stag,
Packit 961e70
	     const void *buf, uint32_t len, void *context, psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Send a non-blocking MQ message
Packit 961e70
 *
Packit 961e70
 * Function to initiate the send of a non-blocking MQ message, whereby the
Packit 961e70
 * user guarantees that the source data will remain unmodified until the send
Packit 961e70
 * is locally completed through a call such as @ref psm2_mq_wait or @ref
Packit 961e70
 * psm2_mq_test.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] dest Destination EP address
Packit 961e70
 * @param[in] flags Message flags, currently:
Packit 961e70
 *            @li PSM2_MQ_FLAG_SENDSYNC tells PSM to send the message
Packit 961e70
 *            synchronously, meaning that the message will not be sent until
Packit 961e70
 *            the receiver acknowledges that it has matched the send with a
Packit 961e70
 *            receive buffer.
Packit 961e70
 * @param[in] stag Message Send Tag, array of three 32-bit values.
Packit 961e70
 * @param[in] buf Source buffer pointer
Packit 961e70
 * @param[in] len Length of message starting at @c buf.
Packit 961e70
 * @param[in] context Optional user-provided pointer available in @ref
Packit 961e70
 *                    psm2_mq_status2_t when the send is locally completed.
Packit 961e70
 * @param[out] req PSM MQ Request handle created by the non-blocking send, to
Packit 961e70
 *                 be used for explicitly controlling message completion.
Packit 961e70
 *
Packit 961e70
 * @post The source buffer is not reusable and the send is not locally complete
Packit 961e70
 *       until its request is completed by either @ref psm2_mq_test or @ref
Packit 961e70
 *       psm2_mq_wait.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * @note This send function has been implemented to suit MPI_Isend.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The message has been successfully initiated.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
   	psm2_mq_req_t
Packit 961e70
   	non_blocking_send(const psm2_mq_t mq, psm2_epaddr_t dest_ep,
Packit 961e70
   	                      const void *buf, uint32_t len,
Packit 961e70
   	     		 int context_id, int send_tag, const my_request_t *req)
Packit 961e70
   	{
Packit 961e70
   	    psm2_mq_req_t req_mq;
Packit 961e70
   	    // Set up our send tag, assume that "my_rank" is global and represents
Packit 961e70
   	    // the rank of this process in the job
Packit 961e70
   	    psm2_mq_tag_t tag;
Packit 961e70
   	    tag.tag[0] = send_tag;
Packit 961e70
   	    tag.tag[1] = my_rank;
Packit 961e70
   	    tag.tag[2] = context_id;
Packit 961e70
  
Packit 961e70
   	    psm2_mq_isend(mq, dest_ep,
Packit 961e70
   	                 0, // no flags
Packit 961e70
   	                 &tag,
Packit 961e70
   	                 buf,
Packit 961e70
   	                 len,
Packit 961e70
   	                 req, // this req is available in psm2_mq_status2_t when one
Packit 961e70
   	                      // of the synchronization functions is called.
Packit 961e70
   	                 &req_mq);
Packit 961e70
   	    return req_mq;
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_isend2(psm2_mq_t mq, psm2_epaddr_t dest, uint32_t flags,
Packit 961e70
	      psm2_mq_tag_t *stag, const void *buf, uint32_t len, void *context,
Packit 961e70
	      psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Try to Probe if a message is received matching tag selection
Packit 961e70
 * criteria
Packit 961e70
 *
Packit 961e70
 * Function to verify if a message matching the supplied tag and tag selectors
Packit 961e70
 * has been received.  The message is not fully matched until the user
Packit 961e70
 * provides a buffer with the successfully matching tag selection criteria
Packit 961e70
 * through @ref psm2_mq_irecv.
Packit 961e70
 * Probing for messages may be useful if the size of the
Packit 961e70
 * message to be received is unknown, in which case its size will be
Packit 961e70
 * available in the @c msg_length member of the returned @c status.
Packit 961e70
 *
Packit 961e70
 * Function ensures progress if matching request wasn’t found
Packit 961e70
 * after the first attempt.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] rtag Message receive tag
Packit 961e70
 * @param[in] rtagsel Message receive tag selector
Packit 961e70
 * @param[out] status Upon return, @c status is filled with information
Packit 961e70
 *                    regarding the matching send.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The iprobe is successful and status is updated if non-NULL.
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The iprobe is unsuccessful and status is
Packit 961e70
 *                               unchanged.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_iprobe(psm2_mq_t mq, uint64_t rtag, uint64_t rtagsel,
Packit 961e70
	      psm2_mq_status_t *status);
Packit 961e70
Packit 961e70
/** @brief Try to Probe if a message is received matching source and tag
Packit 961e70
 * selection criteria
Packit 961e70
 *
Packit 961e70
 * Function to verify if a message matching the supplied source, tag, and tag
Packit 961e70
 * selectors has been received.  The message is not fully matched until the
Packit 961e70
 * user provides a buffer with the successfully matching tag selection criteria
Packit 961e70
 * through @ref psm2_mq_irecv.  Probing for messages may be useful if the size
Packit 961e70
 * of the message to be received is unknown, in which case its size will be
Packit 961e70
 * available in the @c msg_length member of the returned @c status.
Packit 961e70
 *
Packit 961e70
 * Function ensures progress if matching request wasn’t found
Packit 961e70
 * after the first attempt.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] src Source (sender's) epaddr (may be PSM2_MQ_ANY_ADDR)
Packit 961e70
 * @param[in] rtag Message receive tag
Packit 961e70
 * @param[in] rtagsel Message receive tag selector
Packit 961e70
 * @param[out] status Upon return, @c status is filled with information
Packit 961e70
 *                    regarding the matching send.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The iprobe is successful and status is updated if non-NULL.
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The iprobe is unsuccessful and status is
Packit 961e70
 *                               unchanged.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_iprobe2(psm2_mq_t mq, psm2_epaddr_t src, psm2_mq_tag_t *rtag,
Packit 961e70
	       psm2_mq_tag_t *rtagsel, psm2_mq_status2_t *status);
Packit 961e70
Packit 961e70
/** @brief Try to Probe if a message is received matching tag selection
Packit 961e70
 * criteria
Packit 961e70
 *
Packit 961e70
 * Function to verify if a message matching the supplied source, tag, and tag
Packit 961e70
 * selectors has been received.  If a match is successful, the message is
Packit 961e70
 * removed from the matching queue and returned as a request object.  The
Packit 961e70
 * message can be received using @ref psm2_mq_imrecv.  It is erroneous to use
Packit 961e70
 * the request object returned by @ref psm2_mq_improbe for any purpose other
Packit 961e70
 * than passing to @ref psm2_mq_imrecv.  Probing for messages may be useful if
Packit 961e70
 * the size of the message to be received is unknown, in which case its size
Packit 961e70
 * will be available in the @c msg_length member of the returned @c status.
Packit 961e70
 *
Packit 961e70
 * Function ensures progress if matching request wasn’t found
Packit 961e70
 * after the first attempt.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] rtag Message receive tag
Packit 961e70
 * @param[in] rtagsel Message receive tag selector
Packit 961e70
 * @param[out] req PSM MQ Request handle, to be used for receiving the matched
Packit 961e70
 *                 message.
Packit 961e70
 * @param[out] status Upon return, @c status is filled with information
Packit 961e70
 *                    regarding the matching send.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The iprobe is successful and status is updated if non-NULL.
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The iprobe is unsuccessful and status is unchanged.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_improbe(psm2_mq_t mq, uint64_t rtag, uint64_t rtagsel, psm2_mq_req_t *req,
Packit 961e70
	       psm2_mq_status_t *status);
Packit 961e70
Packit 961e70
/** @brief Try to Probe if a message is received matching source and tag
Packit 961e70
 * selection criteria
Packit 961e70
 *
Packit 961e70
 * Function to verify if a message matching the supplied tag and tag selectors
Packit 961e70
 * has been received.  If a match is successful, the message is removed from
Packit 961e70
 * the matching queue and returned as a request object.  The message can be
Packit 961e70
 * received using @ref psm2_mq_imrecv.  It is erroneous to use the request
Packit 961e70
 * object returned by @ref psm2_mq_improbe for any purpose other than passing to
Packit 961e70
 * @ref psm2_mq_imrecv.  Probing for messages may be useful if the size of the
Packit 961e70
 * message to be received is unknown, in which case its size will be available
Packit 961e70
 * in the @c msg_length member of the returned @c status.
Packit 961e70
 *
Packit 961e70
 * Function ensures progress if matching request wasn’t found
Packit 961e70
 * after the first attempt.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] src Source (sender's) epaddr (may be PSM2_MQ_ANY_ADDR)
Packit 961e70
 * @param[in] rtag Message receive tag
Packit 961e70
 * @param[in] rtagsel Message receive tag selector
Packit 961e70
 * @param[out] reqo PSM MQ Request handle, to be used for receiving the matched
Packit 961e70
 *                  message.
Packit 961e70
 * @param[out] status Upon return, @c status is filled with information
Packit 961e70
 *                    regarding the matching send.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The iprobe is successful and status is updated if non-NULL.
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The iprobe is unsuccessful and status is unchanged.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_improbe2(psm2_mq_t mq, psm2_epaddr_t src, psm2_mq_tag_t *rtag,
Packit 961e70
		psm2_mq_tag_t *rtagsel, psm2_mq_req_t *reqo,
Packit 961e70
		psm2_mq_status2_t *status);
Packit 961e70
Packit 961e70
/** @brief Query for non-blocking requests ready for completion.
Packit 961e70
 *
Packit 961e70
 * Function to query a particular MQ for non-blocking requests that are ready
Packit 961e70
 * for completion.  Requests "ready for completion" are not actually considered
Packit 961e70
 * complete by MQ until they are returned to the MQ library through @ref
Packit 961e70
 * psm2_mq_wait or @ref psm2_mq_test.
Packit 961e70
 *
Packit 961e70
 * If the user can deal with consuming request completions in the order in
Packit 961e70
 * which they complete, this function can be used both for completions and for
Packit 961e70
 * ensuring progress.  The latter requirement is satisfied when the user
Packit 961e70
 * peeks an empty completion queue as a side effect of always aggressively
Packit 961e70
 * peeking and completing all an MQ's requests ready for completion.
Packit 961e70
 *
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in,out] req MQ non-blocking request
Packit 961e70
 * @param[in] status Optional MQ status, can be NULL.
Packit 961e70
 *
Packit 961e70
 * @post The user has ensured progress if the function returns @ref
Packit 961e70
 *       PSM2_MQ_NO_COMPLETIONS
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The peek is successful and @c req is updated with a request
Packit 961e70
 *                ready for completion.  If @c status is non-NULL, it is also
Packit 961e70
 *                updated.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The peek is not successful, meaning that there
Packit 961e70
 *                               are no further requests ready for completion.
Packit 961e70
 *                               The contents of @c req and @c status remain
Packit 961e70
 *                               unchanged.
Packit 961e70
 * @code{.c}
Packit 961e70
   	// Example that uses ipeek_mq_ipeek to make progress instead of psm2_poll
Packit 961e70
   	// We return the amount of non-blocking requests that we've completed
Packit 961e70
   	int main_progress_loop(psm2_mq_t mq)
Packit 961e70
   	{
Packit 961e70
   	    int num_completed = 0;
Packit 961e70
   	    psm2_mq_req_t req;
Packit 961e70
   	    psm2_mq_status_t status;
Packit 961e70
   	    psm2_error_t err;
Packit 961e70
   	    my_request_t *myreq;
Packit 961e70
  
Packit 961e70
   	    do {
Packit 961e70
   	        err = psm2_mq_ipeek(mq, &req,
Packit 961e70
   	                           NULL); // No need for status in ipeek here
Packit 961e70
   	        if (err == PSM2_MQ_NO_COMPLETIONS)
Packit 961e70
   	            return num_completed;
Packit 961e70
   	        else if (err != PSM2_OK)
Packit 961e70
   	            goto errh;
Packit 961e70
   	        num_completed++;
Packit 961e70
  
Packit 961e70
   	        // We obtained 'req' at the head of the completion queue.  We can
Packit 961e70
   	        // now free the request with PSM and obtain our original reques
Packit 961e70
   	        // from the status' context
Packit 961e70
   	        err = psm2_mq_test(&req, // will be marked as invalid
Packit 961e70
   	                          &status); // we need the status
Packit 961e70
   	        myreq = (my_request_t *) status.context;
Packit 961e70
  
Packit 961e70
   	        // handle the completion for myreq whether myreq is a posted receive
Packit 961e70
   	        // or a non-blocking send.
Packit 961e70
   	   }
Packit 961e70
   	   while (1);
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_ipeek(psm2_mq_t mq, psm2_mq_req_t *req, psm2_mq_status_t *status);
Packit 961e70
Packit 961e70
/** @brief Query for non-blocking requests ready for completion.
Packit 961e70
 *
Packit 961e70
 * Function to query a particular MQ for non-blocking requests that are ready
Packit 961e70
 * for completion.  Requests "ready for completion" are not actually considered
Packit 961e70
 * complete by MQ until they are returned to the MQ library through @ref
Packit 961e70
 * psm2_mq_wait or @ref psm2_mq_test.
Packit 961e70
 *
Packit 961e70
 * If the user can deal with consuming request completions in the order in
Packit 961e70
 * which they complete, this function can be used both for completions and for
Packit 961e70
 * ensuring progress.  The latter requirement is satisfied when the user
Packit 961e70
 * peeks an empty completion queue as a side effect of always aggressively
Packit 961e70
 * peeking and completing all an MQ's requests ready for completion.
Packit 961e70
 *
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in,out] req MQ non-blocking request
Packit 961e70
 * @param[in] status Optional MQ status, can be NULL.
Packit 961e70
 *
Packit 961e70
 * @post The user has ensured progress if the function returns @ref
Packit 961e70
 *       PSM2_MQ_NO_COMPLETIONS
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as different MQ arguments are used in each of the calls.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The peek is successful and @c req is updated with a request
Packit 961e70
 *                ready for completion.  If @c status is non-NULL, it is also
Packit 961e70
 *                updated.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The peek is not successful, meaning that there
Packit 961e70
 *                            are no further requests ready for completion.
Packit 961e70
 *                            The contents of @c req and @c status remain
Packit 961e70
 *                            unchanged.
Packit 961e70
 * @code{.c}
Packit 961e70
   	// Example that uses ipeek_mq_ipeek to make progress instead of psm2_poll
Packit 961e70
   	// We return the amount of non-blocking requests that we've completed
Packit 961e70
   	int main_progress_loop(psm2_mq_t mq)
Packit 961e70
   	{
Packit 961e70
   	    int num_completed = 0;
Packit 961e70
   	    psm2_mq_req_t req;
Packit 961e70
   	    psm2_mq_status2_t status;
Packit 961e70
   	    psm2_error_t err;
Packit 961e70
   	    my_request_t *myreq;
Packit 961e70
  
Packit 961e70
   	    do {
Packit 961e70
   	        err = psm2_mq_ipeek2(mq, &req,
Packit 961e70
   	                           NULL); // No need for status in ipeek here
Packit 961e70
   	        if (err == PSM2_MQ_NO_COMPLETIONS)
Packit 961e70
   	            return num_completed;
Packit 961e70
   	        else if (err != PSM2_OK)
Packit 961e70
   	            goto errh;
Packit 961e70
   	        num_completed++;
Packit 961e70
  
Packit 961e70
   	        // We obtained 'req' at the head of the completion queue.  We can
Packit 961e70
   	        // now free the request with PSM and obtain our original reques
Packit 961e70
   	        // from the status' context
Packit 961e70
   	        err = psm2_mq_test2(&req, // will be marked as invalid
Packit 961e70
   	                          &status); // we need the status
Packit 961e70
   	        myreq = (my_request_t *) status.context;
Packit 961e70
  
Packit 961e70
   	        // handle the completion for myreq whether myreq is a posted receive
Packit 961e70
   	        // or a non-blocking send.
Packit 961e70
   	   }
Packit 961e70
   	   while (1);
Packit 961e70
   	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_ipeek2(psm2_mq_t mq, psm2_mq_req_t *req, psm2_mq_status2_t *status);
Packit 961e70
Packit 961e70
/** @brief User defined Callback function handling copy of MQ request into user datatype
Packit 961e70
 *
Packit 961e70
 * Callback function used to convert an MQ request into a user's desired
Packit 961e70
 * status structure. The user's callback function converts the MQ request into
Packit 961e70
 * the provided status_array at the specified index.
Packit 961e70
 *
Packit 961e70
 * @param[in] req MQ External non-blocking Request structure
Packit 961e70
 * @param[in] status_array Array of User defined status datatypes
Packit 961e70
 * @param[in] entry_index Index in array where the converted request will be
Packit 961e70
 *                  stored if successful
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.
Packit 961e70
 *
Packit 961e70
 * @retval < 0 The MQ conversion failed with a user defined error.
Packit 961e70
 *
Packit 961e70
 * @retval 0 The MQ was successfully processed, but was not saved
Packit 961e70
 *                 in the provided @c status_array.
Packit 961e70
 *
Packit 961e70
 * @retval 1 The MQ was successfully processed and was saved in the
Packit 961e70
 *                 @c status_array at the specified index.
Packit 961e70
 *
Packit 961e70
 * @retval >1 The MQ was successfully processed and was saved in the
Packit 961e70
 *                 @c status_array at the specified index. This should
Packit 961e70
 *                 be the last MQ converted in the batch, even if there
Packit 961e70
 *                 are still spaces in @c status_array.
Packit 961e70
 */
Packit 961e70
typedef int (*psmi_mq_status_copy_user_t) (struct psm2_mq_req_user *req,
Packit 961e70
        void *status_array, int entry_index);
Packit 961e70
Packit 961e70
/** @brief Check and dequeue MQ requests into a user's status array using a callback.
Packit 961e70
 *
Packit 961e70
 * Function to atomically check and dequeue MQ entries from the completed
Packit 961e70
 * queue and copy the MQ requests into a user's status datatype through a
Packit 961e70
 * status_copy callback function.
Packit 961e70
 *
Packit 961e70
 * Once the MQ request has been successfully converted by the callback, the
Packit 961e70
 * MQ request is freed and the next entry is processed making the supplied
Packit 961e70
 * Request pointer invalid.
Packit 961e70
 *
Packit 961e70
 * The variable "count" passed in will only be increased if the MQ request was
Packit 961e70
 * successfully stored into the user's passed in array. Otherwise the count
Packit 961e70
 * variable is unchanged.
Packit 961e70
 *
Packit 961e70
 * NOTE: a count of 0 passed into psm2_mq_ipeek_dequeue_multi will result in
Packit 961e70
 * no MQ elements being processed.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] status_array Array of User defined status datatypes
Packit 961e70
 * @param[in] status_copy Callback function pointer to convert
Packit 961e70
 *                  MQ to caller datatype
Packit 961e70
 * @param[in/out] count [in]Size of status_array, [out]number of elements
Packit 961e70
 *                  populated into status_array or user's error return code
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The dequeue operation was successful and populated the
Packit 961e70
 *                  full @c status_array up to @c count entries. The parameter
Packit 961e70
 *                  @c count is equal to the count passed in by the user.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The dequeue operation was not able to read
Packit 961e70
 *                  @c count entries into the @c status_array. The number
Packit 961e70
 *                  of entries that were successfully written to the
Packit 961e70
 *                  @c status_array is set in the @c count for the user.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_INTERNAL_ERR The @c status_copy failed to successfully
Packit 961e70
 *                  copy the status entry into the user's datatype.
Packit 961e70
 *                  @c count is set to the return code from the
Packit 961e70
 *                  @c status_copy.
Packit 961e70
 */
Packit 961e70
 psm2_error_t
Packit 961e70
 psm2_mq_ipeek_dequeue_multi(psm2_mq_t mq, void *status_array,
Packit 961e70
        psmi_mq_status_copy_user_t status_copy, int *count);
Packit 961e70
Packit 961e70
/** @brief Check and dequeue the first request entry from the completed queue.
Packit 961e70
 *
Packit 961e70
 * Function to atomically check and dequeue the first entry from the completed
Packit 961e70
 * queue. It must be paired with function psm2_mq_req_free, which returns the
Packit 961e70
 * request to PSM2 library.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[out] req PSM MQ Request handle, to be used for receiving the matched
Packit 961e70
 *                  message.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The dequeue operation was successful and @c req is updated
Packit 961e70
 *                 with a request ready for completion.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The dequeue operation was not successful,
Packit 961e70
 *                            meaning that there are no further requests ready
Packit 961e70
 *                            for completion. The contents of @c req remain
Packit 961e70
 *                            unchanged.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_ipeek_dequeue(psm2_mq_t mq, psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/** @brief Return the request to PSM2 library.
Packit 961e70
 *
Packit 961e70
 * Function returns the request previously obtained via psm2_mq_ipeek_dequeue
Packit 961e70
 * to the PSM2 library.
Packit 961e70
 *
Packit 961e70
 * @param[in] mq Matched Queue Handle
Packit 961e70
 * @param[in] req PSM MQ Request handle to be returned to PSM2 library.
Packit 961e70
              If @p req is NULL, no operation is performed.
Packit 961e70
 *
Packit 961e70
 * The following error codes are returned.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK Return of an object to PSM2 library pool was successful.
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_req_free(psm2_mq_t mq, psm2_mq_req_t req);
Packit 961e70
Packit 961e70
/** @brief Wait until a non-blocking request completes
Packit 961e70
 *
Packit 961e70
 * Function to wait on requests created from either preposted receive buffers
Packit 961e70
 * or non-blocking sends.  This is the only blocking function in the MQ
Packit 961e70
 * interface and will poll until the request is complete as per the progress
Packit 961e70
 * semantics explained in @ref mq_progress.
Packit 961e70
 *
Packit 961e70
 * @param[in,out] request MQ non-blocking request
Packit 961e70
 * @param[out] status Updated if non-NULL when request successfully completes
Packit 961e70
 *
Packit 961e70
 * @pre The user has obtained a valid MQ request by calling @ref psm2_mq_isend
Packit 961e70
 *      or @ref psm2_mq_irecv and passes a pointer to enough storage to write
Packit 961e70
 *      the output of a @ref psm2_mq_status_t or NULL if status is to be
Packit 961e70
 *      ignored.
Packit 961e70
 *
Packit 961e70
 * @pre Since MQ will internally ensure progress while the user is
Packit 961e70
 *      suspended, the user need not ensure that progress is made prior to
Packit 961e70
 *      calling this function.
Packit 961e70
 *
Packit 961e70
 * @post The request is assigned the value @ref PSM2_MQ_REQINVALID and all
Packit 961e70
 *       associated MQ request storage is released back to the MQ library.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as the requests that are used in each of the calls are
Packit 961e70
 * 	   associated with different MQs.
Packit 961e70
 *
Packit 961e70
 * @remarks
Packit 961e70
 *  @li This function ensures progress on the endpoint as long as the request
Packit 961e70
 *      is incomplete.
Packit 961e70
 *  @li @c status can be NULL, in which case no status is written upon
Packit 961e70
 *      completion.
Packit 961e70
 *  @li If @c request is @ref PSM2_MQ_REQINVALID, the function returns
Packit 961e70
 *      immediately.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The request is complete or the value of @c was
Packit 961e70
 *                @ref PSM2_MQ_REQINVALID.
Packit 961e70
 *
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_wait(psm2_mq_req_t *request, psm2_mq_status_t *status);
Packit 961e70
Packit 961e70
/** @brief Wait until a non-blocking request completes
Packit 961e70
 *
Packit 961e70
 * Function to wait on requests created from either preposted receive buffers
Packit 961e70
 * or non-blocking sends.  This is the only blocking function in the MQ
Packit 961e70
 * interface and will poll until the request is complete as per the progress
Packit 961e70
 * semantics explained in @ref mq_progress.
Packit 961e70
 *
Packit 961e70
 * @param[in,out] request MQ non-blocking request
Packit 961e70
 * @param[out] status Updated if non-NULL when request successfully completes
Packit 961e70
 *
Packit 961e70
 * @pre The user has obtained a valid MQ request by calling @ref psm2_mq_isend
Packit 961e70
 *      or @ref psm2_mq_irecv and passes a pointer to enough storage to write
Packit 961e70
 *      the output of a @ref psm2_mq_status2_t or NULL if status is to be
Packit 961e70
 *      ignored.
Packit 961e70
 *
Packit 961e70
 * @pre Since MQ will internally ensure progress while the user is
Packit 961e70
 *      suspended, the user need not ensure that progress is made prior to
Packit 961e70
 *      calling this function.
Packit 961e70
 *
Packit 961e70
 * @post The request is assigned the value @ref PSM2_MQ_REQINVALID and all
Packit 961e70
 *       associated MQ request storage is released back to the MQ library.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as the requests that are used in each of the calls are
Packit 961e70
 * 	   associated with different MQs.
Packit 961e70
 *
Packit 961e70
 * @remarks
Packit 961e70
 *  @li This function ensures progress on the endpoint as long as the request
Packit 961e70
 *      is incomplete.
Packit 961e70
 *  @li @c status can be NULL, in which case no status is written upon
Packit 961e70
 *      completion.
Packit 961e70
 *  @li If @c request is @ref PSM2_MQ_REQINVALID, the function returns
Packit 961e70
 *      immediately.
Packit 961e70
 *
Packit 961e70
 * The following error code is returned.  Other errors are handled by the PSM
Packit 961e70
 * error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The request is complete or the value of @c was
Packit 961e70
 *                @ref PSM2_MQ_REQINVALID.
Packit 961e70
 *
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_wait2(psm2_mq_req_t *request, psm2_mq_status2_t *status);
Packit 961e70
Packit 961e70
/** @brief Test if a non-blocking request is complete
Packit 961e70
 *
Packit 961e70
 * Function to test requests created from either preposted receive buffers or
Packit 961e70
 * non-blocking sends for completion.  Unlike @ref psm2_mq_wait, this function
Packit 961e70
 * tests @c request for completion and @e never ensures progress directly or
Packit 961e70
 * indirectly.  It is up to the user to employ some of the progress functions
Packit 961e70
 * described in @ref mq_progress to ensure progress if the user chooses to
Packit 961e70
 * exclusively test requests for completion.
Packit 961e70
 *
Packit 961e70
 * Testing a request for completion @e never internally ensure progress in
Packit 961e70
 * order to be useful to construct higher-level completion tests over arrays to
Packit 961e70
 * test some, all or any request that has completed.  For testing arrays of
Packit 961e70
 * requests, it is preferable for performance reasons to only ensure progress
Packit 961e70
 * once before testing a set of requests for completion.
Packit 961e70
 *
Packit 961e70
 * @param[in,out] request MQ non-blocking request
Packit 961e70
 * @param[out] status Updated if non-NULL and the request successfully
Packit 961e70
 * completes
Packit 961e70
 *
Packit 961e70
 * @pre The user has obtained a valid MQ request by calling @ref psm2_mq_isend
Packit 961e70
 *      or @ref psm2_mq_irecv and passes a pointer to enough storage to write
Packit 961e70
 *      the output of a @ref psm2_mq_status_t or NULL if status is to be
Packit 961e70
 *      ignored.
Packit 961e70
 *
Packit 961e70
 * @pre The user has ensured progress on the Matched Queue if @ref
Packit 961e70
 *      psm2_mq_test is exclusively used for guaranteeing request completions.
Packit 961e70
 *
Packit 961e70
 * @post If the request is complete, the request is assigned the value @ref
Packit 961e70
 *       PSM2_MQ_REQINVALID and all associated MQ request storage is released
Packit 961e70
 *       back to the MQ library. If the request is incomplete, the contents of
Packit 961e70
 *       @c request is unchanged.
Packit 961e70
 *
Packit 961e70
 * @post The user will ensure progress on the Matched Queue if @ref
Packit 961e70
 *       psm2_mq_test is exclusively used for guaranteeing request completions.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as the requests that are used in each of the calls are
Packit 961e70
 * 	   associated with different MQs.
Packit 961e70
 *
Packit 961e70
 * The following two errors are always returned.  Other errors are handled by
Packit 961e70
 * the PSM error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The request is complete and @c request is set to @ref
Packit 961e70
 *                PSM2_MQ_REQINVALID or the value of @c was PSM2_MQ_REQINVALID
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The request is not complete and @c request is
Packit 961e70
 *                           unchanged.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
  	// Function that returns the first completed request in an array
Packit 961e70
  	// of requests.
Packit 961e70
  	void *
Packit 961e70
  	user_testany(psm2_ep_t ep, psm2_mq_req_t *allreqs, int nreqs)
Packit 961e70
  	{
Packit 961e70
  	  int i;
Packit 961e70
  	  void *context = NULL;
Packit 961e70
  	
Packit 961e70
  	  // Ensure progress only once
Packit 961e70
  	  psm2_poll(ep);
Packit 961e70
  	
Packit 961e70
  	  // Test for at least one completion and return it's context
Packit 961e70
  	  psm2_mq_status_t stat;
Packit 961e70
  	  for (i = 0; i < nreqs; i++) {
Packit 961e70
  	    if (psm2_mq_test(&allreqs[i], &stat) == PSM2_OK) {
Packit 961e70
  	      context = stat.context;
Packit 961e70
  	      break;
Packit 961e70
  	    }
Packit 961e70
  	  }
Packit 961e70
  	  return context;
Packit 961e70
  	}
Packit 961e70
  @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_test(psm2_mq_req_t *request, psm2_mq_status_t *status);
Packit 961e70
Packit 961e70
/** @brief Test if a non-blocking request is complete
Packit 961e70
 *
Packit 961e70
 * Function to test requests created from either preposted receive buffers or
Packit 961e70
 * non-blocking sends for completion.  Unlike @ref psm2_mq_wait, this function
Packit 961e70
 * tests @c request for completion and @e never ensures progress directly or
Packit 961e70
 * indirectly.  It is up to the user to employ some of the progress functions
Packit 961e70
 * described in @ref mq_progress to ensure progress if the user chooses to
Packit 961e70
 * exclusively test requests for completion.
Packit 961e70
 *
Packit 961e70
 * Testing a request for completion @e never internally ensure progress in
Packit 961e70
 * order to be useful to construct higher-level completion tests over arrays to
Packit 961e70
 * test some, all or any request that has completed.  For testing arrays of
Packit 961e70
 * requests, it is preferable for performance reasons to only ensure progress
Packit 961e70
 * once before testing a set of requests for completion.
Packit 961e70
 *
Packit 961e70
 * @param[in,out] request MQ non-blocking request
Packit 961e70
 * @param[out] status Updated if non-NULL and the request successfully
Packit 961e70
 * completes
Packit 961e70
 *
Packit 961e70
 * @pre The user has obtained a valid MQ request by calling @ref psm2_mq_isend
Packit 961e70
 *      or @ref psm2_mq_irecv and passes a pointer to enough storage to write
Packit 961e70
 *      the output of a @ref psm2_mq_status2_t or NULL if status is to be
Packit 961e70
 *      ignored.
Packit 961e70
 *
Packit 961e70
 * @pre The user has ensured progress on the Matched Queue if @ref
Packit 961e70
 *      psm2_mq_test is exclusively used for guaranteeing request completions.
Packit 961e70
 *
Packit 961e70
 * @post If the request is complete, the request is assigned the value @ref
Packit 961e70
 *       PSM2_MQ_REQINVALID and all associated MQ request storage is released
Packit 961e70
 *       back to the MQ library. If the request is incomplete, the contents of
Packit 961e70
 *       @c request is unchanged.
Packit 961e70
 *
Packit 961e70
 * @post The user will ensure progress on the Matched Queue if @ref
Packit 961e70
 *       psm2_mq_test is exclusively used for guaranteeing request completions.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as the requests that are used in each of the calls are
Packit 961e70
 * 	   associated with different MQs.
Packit 961e70
 *
Packit 961e70
 * The following two errors are always returned.  Other errors are handled by
Packit 961e70
 * the PSM error handler (@ref psm2_error_register_handler).
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The request is complete and @c request is set to @ref
Packit 961e70
 *                PSM2_MQ_REQINVALID or the value of @c was PSM2_MQ_REQINVALID
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The request is not complete and @c request is
Packit 961e70
 *                           unchanged.
Packit 961e70
 *
Packit 961e70
 * @code{.c}
Packit 961e70
  	// Function that returns the first completed request in an array
Packit 961e70
  	// of requests.
Packit 961e70
  	void *
Packit 961e70
  	user_testany(psm2_ep_t ep, psm2_mq_req_t *allreqs, int nreqs)
Packit 961e70
  	{
Packit 961e70
  	  int i;
Packit 961e70
  	  void *context = NULL;
Packit 961e70
  	
Packit 961e70
  	  // Ensure progress only once
Packit 961e70
  	  psm2_poll(ep);
Packit 961e70
  	
Packit 961e70
  	  // Test for at least one completion and return it's context
Packit 961e70
  	  psm2_mq_status2_t stat;
Packit 961e70
  	  for (i = 0; i < nreqs; i++) {
Packit 961e70
  	    if (psm2_mq_test2(&allreqs[i], &stat) == PSM2_OK) {
Packit 961e70
  	      context = stat.context;
Packit 961e70
  	      break;
Packit 961e70
  	    }
Packit 961e70
  	  }
Packit 961e70
  	  return context;
Packit 961e70
  	}
Packit 961e70
   @endcode
Packit 961e70
 */
Packit 961e70
psm2_error_t
Packit 961e70
psm2_mq_test2(psm2_mq_req_t *request, psm2_mq_status2_t *status);
Packit 961e70
Packit 961e70
/** @brief Cancel a preposted request
Packit 961e70
 *
Packit 961e70
 * Function to cancel a preposted receive request returned by @ref
Packit 961e70
 * psm2_mq_irecv.  It is currently illegal to cancel a send request initiated
Packit 961e70
 * with @ref psm2_mq_isend.
Packit 961e70
 *
Packit 961e70
 * @pre The user has obtained a valid MQ request by calling @ref psm2_mq_isend.
Packit 961e70
 *
Packit 961e70
 * @post Whether the cancel is successful or not, the user returns the
Packit 961e70
 *       request to the library by way of @ref psm2_mq_test or @ref
Packit 961e70
 *       psm2_mq_wait.
Packit 961e70
 *
Packit 961e70
 * @remark This function may be called simultaneously from multiple threads
Packit 961e70
 * 	   as long as the requests that are used in each of the calls are
Packit 961e70
 * 	   associated with different MQs.
Packit 961e70
 *
Packit 961e70
 * Only the two following errors can be returned directly, without being
Packit 961e70
 * handled by the error handler (@ref psm2_error_register_handler):
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_OK The request could be successfully cancelled such that the
Packit 961e70
 *                preposted receive buffer could be removed from the preposted
Packit 961e70
 *                receive queue before a match occurred. The associated @c
Packit 961e70
 *                request remains unchanged and the user must still return
Packit 961e70
 *                the storage to the MQ library.
Packit 961e70
 *
Packit 961e70
 * @retval PSM2_MQ_NO_COMPLETIONS The request could not be successfully cancelled
Packit 961e70
 *                           since the preposted receive buffer has already
Packit 961e70
 *                           matched an incoming message.  The @c request
Packit 961e70
 *                           remains unchanged.
Packit 961e70
 *
Packit 961e70
 */
Packit 961e70
psm2_error_t psm2_mq_cancel(psm2_mq_req_t *req);
Packit 961e70
Packit 961e70
/*! @brief MQ statistics structure */
Packit 961e70
struct psm2_mq_stats {
Packit 961e70
	/** Bytes received into a matched user buffer */
Packit 961e70
	uint64_t rx_user_bytes;
Packit 961e70
	/** Messages received into a matched user buffer */
Packit 961e70
	uint64_t rx_user_num;
Packit 961e70
	/** Bytes received into an unmatched system buffer */
Packit 961e70
	uint64_t rx_sys_bytes;
Packit 961e70
	/** Messages received into an unmatched system buffer */
Packit 961e70
	uint64_t rx_sys_num;
Packit 961e70
Packit 961e70
	/** Total Messages transmitted (shm and hfi) */
Packit 961e70
	uint64_t tx_num;
Packit 961e70
	/** Messages transmitted eagerly */
Packit 961e70
	uint64_t tx_eager_num;
Packit 961e70
	/** Bytes transmitted eagerly */
Packit 961e70
	uint64_t tx_eager_bytes;
Packit 961e70
	/** Messages transmitted using expected TID mechanism */
Packit 961e70
	uint64_t tx_rndv_num;
Packit 961e70
	/** Bytes transmitted using expected TID mechanism */
Packit 961e70
	uint64_t tx_rndv_bytes;
Packit 961e70
	/** Messages transmitted (shm only) */
Packit 961e70
	uint64_t tx_shm_num;
Packit 961e70
	/** Messages received through shm */
Packit 961e70
	uint64_t rx_shm_num;
Packit 961e70
Packit 961e70
	/** Number of system buffers allocated  */
Packit 961e70
	uint64_t rx_sysbuf_num;
Packit 961e70
	/** Bytes allcoated for system buffers */
Packit 961e70
	uint64_t rx_sysbuf_bytes;
Packit 961e70
Packit 961e70
	/** Internally reserved for future use */
Packit 961e70
	uint64_t _reserved[16];
Packit 961e70
};
Packit 961e70
Packit 961e70
#define PSM2_MQ_NUM_STATS    13	/**< How many stats are currently used in @ref psm2_mq_stats */
Packit 961e70
Packit 961e70
/*! @see psm2_mq_stats */
Packit 961e70
	typedef struct psm2_mq_stats psm2_mq_stats_t;
Packit 961e70
Packit 961e70
/** @brief Retrieve statistics from an instantiated MQ */
Packit 961e70
	void
Packit 961e70
	 psm2_mq_get_stats(psm2_mq_t mq, psm2_mq_stats_t *stats);
Packit 961e70
Packit 961e70
/*! @} */
Packit 961e70
#ifdef __cplusplus
Packit 961e70
}				/* extern "C" */
Packit 961e70
#endif
Packit 961e70
#endif