172 строки
4.7 KiB
C
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 */
|