1
1
openmpi/ompi/mca/btl/pcie/btl_pcie_fifo.h

172 строки
4.7 KiB
C

/*
* Copyright (c) 2007 Los Alamos National Security, LLC.
* All righs reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef BTL_PCIE_FIFO_H
#define BTL_PCIE_FIFO_H
#include "ompi_config.h"
#include "ompi/constants.h"
#include "opal/threads/mutex.h"
#include "opal/types.h"
#include "ompi/mca/btl/base/btl_base_error.h"
BEGIN_C_DECLS
typedef uint64_t btl_pcie_fifo_entry_t;
#define BTL_PCIE_FIFO_TYPE_MASK 0x8000000000000000
#define BTL_PCIE_FIFO_DATA_MASK 0x7FFFFFFFFFFFFFFF
#define BTL_PCIE_FIFO_TYPE_ACK 0x0000000000000000
#define BTL_PCIE_FIFO_TYPE_SEND 0x8000000000000000
struct btl_pcie_fifo_t {
/* number of entries in queue */
uint32_t fifo_len;
/* for sender: next place to write
* for receiver: next place to read */
uint32_t current_index;
/* for sender: number of entries "in flight". Must always be less
than or equal to fifo_len */
uint32_t num_outstanding;
uint32_t mask;
/* the actual buffer */
btl_pcie_fifo_entry_t* queue;
};
typedef struct btl_pcie_fifo_t btl_pcie_fifo_t;
/**
* Initialize fifo structure
*
* Initialize send/recv fifo structure. The fifo structure does
* double duty of maintaining both the sender and receiver. This
* function initializes the send view of the fifo structure, for
* use to receive messages. fifo_get_msg() should not be called on
* this fifo.
*
* @note fifo_len must match the value given to the matching
* fifo_init_recv(), although there are no checks to verify this.
*
* @param[in] fifo A pointer to a fifo structure to be
* initialized
* @param[in] fifo_len Requested length of the fifo queue
* @param[in] queue_space Space for the receive queue (remote pointer)
*
* @retval OMPI_SUCCESS Everything worked
* @retval OMPI_ERROR Good luck!
*/
int ompi_btl_pcie_fifo_init_send(btl_pcie_fifo_t *fifo,
unsigned int fifo_len,
void *queue_space);
/**
* Initialize fifo structure
*
* Initialize send/recv fifo structure. The fifo structure does
* double duty of maintaining both the sender and receiver. This
* function initializes the receive view of the fifo structure, for
* use to receive messages. fifo_set_msg() should not be called on
* this fifo.
*
* @note fifo_len must match the value given to the matching
* fifo_init_send(), although there are no checks to verify this.
*
* @param[in] fifo A pointer to a fifo structure to be
* initialized
* @param[in] fifo_len Requested length of the fifo queue
* @param[in] queue_space Space for the receive queue (local pointer)
* @param[in] queue_space_len Length of queue_space
*
* @retval OMPI_SUCCESS Everything worked
* @retval OMPI_ERROR Good luck!
*/
int ompi_btl_pcie_fifo_init_recv(btl_pcie_fifo_t *fifo,
unsigned int fifo_len,
void *queue_space,
size_t queue_space_len);
int ompi_btl_pcie_fifo_finalize(btl_pcie_fifo_t *fifo);
/**
* Read a message from the queue
*
* Read a message from the queue
*
* @param[in] fifo The receive view of the fifo
*
* @return A non-zero message or 0 if no new messages are
* available.
*/
static inline btl_pcie_fifo_entry_t
ompi_btl_pcie_fifo_get_msg(btl_pcie_fifo_t *fifo)
{
/* BWB - TODO - if we ever want to be multi-threaded, we'll
need to fix this */
btl_pcie_fifo_entry_t ret = 0;
if (0 != (ret = fifo->queue[fifo->current_index])) {
fifo->queue[fifo->current_index] = 0;
fifo->current_index++;
fifo->current_index &= fifo->mask;
}
return ret;
}
/**
* Write a message pointer into the queue
*
* Write a message pointer into the send queue view of the fifo.
*
* @param[in] fifo The send view of the fifo
* @param[in] msg The index to the payload to deliver
*
* @retval OMPI_SUCCESS Fifo successfully updated
* @retval OMPI_ERR_RESOURCE_BUSY There was no space in the fifo
*/
static inline int
ompi_btl_pcie_fifo_set_msg(btl_pcie_fifo_t *fifo, btl_pcie_fifo_entry_t msg)
{
uint32_t outstanding;
/* see if we have a slot */
outstanding = OPAL_THREAD_ADD32(&fifo->num_outstanding, 1);
if (outstanding > fifo->fifo_len) {
OPAL_THREAD_ADD32(&fifo->num_outstanding, -1);
return OMPI_ERR_RESOURCE_BUSY;
}
/* now that we have a slot, figure out where it is. Allow the
outstanding to wrap around forever - just mask out the bits we
don't care about. */
outstanding = OPAL_THREAD_ADD32(&fifo->current_index, 1);
outstanding &= fifo->mask;
fifo->queue[outstanding] = msg;
return OMPI_SUCCESS;
}
static inline int
ompi_btl_pcie_fifo_complete_msg(btl_pcie_fifo_t *fifo,
unsigned int num_msgs)
{
OPAL_THREAD_ADD32(&fifo->num_outstanding, -num_msgs);
return OMPI_SUCCESS;
}
END_C_DECLS
#endif /* BTL_PCIE_FIFO_H */