2004-08-25 00:17:44 +04:00
|
|
|
/*
|
2004-11-22 04:38:40 +03:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
|
|
* All rights reserved.
|
2004-11-28 23:09:25 +03:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2004-11-22 04:38:40 +03:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
2004-08-25 00:17:44 +04:00
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _OMPI_FIFO
|
|
|
|
#define _OMPI_FIFO
|
|
|
|
|
|
|
|
#include "include/constants.h"
|
|
|
|
#include "include/sys/cache.h"
|
2005-01-07 20:59:14 +03:00
|
|
|
#include "include/sys/atomic.h"
|
2004-08-25 00:17:44 +04:00
|
|
|
#include "mca/mpool/mpool.h"
|
|
|
|
#include "class/ompi_circular_buffer_fifo.h"
|
|
|
|
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
*
|
|
|
|
* This defines a set of functions to create, and manipulate a FIFO
|
|
|
|
* implemented as a link list of circular buffer FIFO's. FIFO
|
|
|
|
* elements are assumed to be pointers. Pointers are written to
|
|
|
|
* the head, and read from the tail. For thread safety, a spin
|
|
|
|
* lock is provided in the !!!!!ompi_cb_fifo_ctl_t!!!! structure, but it's use must be managed by
|
|
|
|
* the calling routines - this is not by these set of routines.
|
|
|
|
* When a write to a circular buffer queue will overflow that queue,
|
|
|
|
* the next cirular buffer queue if the link list is used, if it is
|
|
|
|
* empty, or a new one is inserted into the list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Structure by the the ompi_fifo routines to keep track of some
|
|
|
|
* extra queue information not needed by the ompi_cb_fifo routines.
|
|
|
|
*/
|
|
|
|
struct ompi_cb_fifo_wrapper_t {
|
|
|
|
|
|
|
|
/* pointer to ompi_cb_fifo_ctl_t structure in use */
|
2004-08-25 02:25:59 +04:00
|
|
|
ompi_cb_fifo_t cb_fifo;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* pointer to next ompi_cb_fifo_ctl_t structure */
|
|
|
|
volatile struct ompi_cb_fifo_wrapper_t *next_fifo_wrapper;
|
|
|
|
|
|
|
|
/* flag indicating if cb_fifo has over flown - need this to force
|
|
|
|
* release of entries already read */
|
|
|
|
volatile bool cb_overflow;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2004-08-25 02:25:59 +04:00
|
|
|
typedef struct ompi_cb_fifo_wrapper_t ompi_cb_fifo_wrapper_t;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* data structure used to describe the fifo */
|
|
|
|
struct ompi_fifo_t {
|
|
|
|
|
|
|
|
/* pointer to head (write) ompi_cb_fifo_t structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
volatile ompi_cb_fifo_wrapper_t *head;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* pointer to tail (read) ompi_cb_fifo_t structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
volatile ompi_cb_fifo_wrapper_t *tail;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
2004-08-28 20:44:20 +04:00
|
|
|
/* locks for thread synchronization */
|
|
|
|
ompi_lock_t head_lock;
|
|
|
|
ompi_lock_t tail_lock;
|
|
|
|
|
2004-08-25 00:17:44 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct ompi_fifo_t ompi_fifo_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* structure used to track which circular buffer slot to write to
|
|
|
|
*/
|
|
|
|
struct cb_slot_t {
|
|
|
|
/* pointer to circular buffer fifo structures */
|
|
|
|
ompi_cb_fifo_t *cb;
|
|
|
|
|
|
|
|
/* index in circular buffer */
|
|
|
|
int index;
|
|
|
|
};
|
2004-08-25 02:25:59 +04:00
|
|
|
|
|
|
|
typedef struct cb_slot_t cb_slot_t;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize a fifo
|
|
|
|
*
|
|
|
|
* @param size_of_cb_fifo Length of fifo array (IN)
|
|
|
|
*
|
|
|
|
* @param fifo_memory_locality_index Locality index to apply to
|
|
|
|
* the fifo array. Not currently
|
|
|
|
* in use (IN)
|
|
|
|
*
|
|
|
|
* @param tail_memory_locality_index Locality index to apply to the
|
|
|
|
* head control structure. Not
|
|
|
|
* currently in use (IN)
|
|
|
|
*
|
|
|
|
* @param tail_memory_locality_index Locality index to apply to the
|
|
|
|
* tail control structure. Not
|
|
|
|
* currently in use (IN)
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @param memory_allocator Pointer to the memory allocator to use
|
|
|
|
* to allocate memory for this fifo. (IN)
|
|
|
|
*
|
|
|
|
* @returncode Error code
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline int ompi_fifo_init(int size_of_cb_fifo, int lazy_free_freq,
|
|
|
|
int fifo_memory_locality_index, int head_memory_locality_index,
|
|
|
|
int tail_memory_locality_index, ompi_fifo_t *fifo,
|
|
|
|
mca_mpool_base_module_t *memory_allocator)
|
|
|
|
{
|
|
|
|
int error_code=OMPI_SUCCESS;
|
2004-08-25 02:25:59 +04:00
|
|
|
size_t len_to_allocate;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t);
|
|
|
|
fifo->head=memory_allocator->mpool_alloc(len_to_allocate,CACHE_LINE_SIZE);
|
|
|
|
if ( NULL == fifo->head) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the circular buffer fifo head structure */
|
|
|
|
error_code=ompi_cb_fifo_init(size_of_cb_fifo, lazy_free_freq,
|
|
|
|
fifo_memory_locality_index, head_memory_locality_index,
|
2004-08-25 02:25:59 +04:00
|
|
|
tail_memory_locality_index,
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo),
|
|
|
|
memory_allocator);
|
2004-08-25 00:17:44 +04:00
|
|
|
if ( OMPI_SUCCESS != error_code ) {
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* finish head initialization */
|
2004-08-25 02:25:59 +04:00
|
|
|
fifo->head->next_fifo_wrapper=
|
2004-08-27 20:32:09 +04:00
|
|
|
(volatile struct ompi_cb_fifo_wrapper_t *)fifo->head; /* only one element
|
2004-08-25 02:25:59 +04:00
|
|
|
in the link list */
|
|
|
|
fifo->head->cb_overflow=false; /* no attempt to overflow the queue */
|
2004-08-28 20:44:20 +04:00
|
|
|
ompi_atomic_unlock(&(fifo->head_lock));
|
|
|
|
ompi_atomic_unlock(&(fifo->tail_lock));
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* set the tail */
|
|
|
|
fifo->tail=fifo->head;
|
|
|
|
|
|
|
|
/* return */
|
2004-08-25 02:25:59 +04:00
|
|
|
return error_code;
|
2004-08-25 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* function to cleanup the fifo
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @param memory_allocator Pointer to the memory allocator to use
|
|
|
|
* to allocate memory for this fifo. (IN)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline int ompi_fifo_free( ompi_fifo_t *fifo,
|
|
|
|
mca_mpool_base_module_t *memory_allocator)
|
|
|
|
{
|
|
|
|
|
|
|
|
int error_code=OMPI_SUCCESS;
|
|
|
|
ompi_cb_fifo_wrapper_t *starting_ff,*ff,*ff_tmp;
|
|
|
|
|
|
|
|
/* loop over the link list of ompi_cb_fifo_wrapper_t structs */
|
2004-08-25 02:25:59 +04:00
|
|
|
starting_ff=(ompi_cb_fifo_wrapper_t *)fifo->head;
|
2004-08-25 00:17:44 +04:00
|
|
|
ff=starting_ff;
|
|
|
|
do {
|
|
|
|
|
|
|
|
/* free the resources associated with the ompi_cb_fifo_t structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
error_code=ompi_cb_fifo_free((ompi_cb_fifo_t *)&(ff->cb_fifo),
|
|
|
|
memory_allocator);
|
2004-08-25 00:17:44 +04:00
|
|
|
if ( OMPI_SUCCESS != error_code ) {
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* next structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
ff_tmp=(ompi_cb_fifo_wrapper_t *)ff->next_fifo_wrapper;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* free the element */
|
|
|
|
memory_allocator->mpool_free(ff);
|
|
|
|
|
|
|
|
ff=ff_tmp;
|
|
|
|
|
2004-08-25 02:25:59 +04:00
|
|
|
} while (ff != starting_ff);
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* return */
|
2004-08-25 02:25:59 +04:00
|
|
|
return error_code;
|
2004-08-25 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Write pointer to the specified slot
|
|
|
|
*
|
|
|
|
* @param slot Slot addressing (IN)
|
|
|
|
*
|
|
|
|
* @param data Pointer value to write in specified slot (IN)
|
|
|
|
*
|
2004-10-12 02:56:46 +04:00
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
2004-08-25 00:17:44 +04:00
|
|
|
* @returncode Slot index data written to
|
|
|
|
*
|
|
|
|
*/
|
2004-08-30 05:25:34 +04:00
|
|
|
static inline int ompi_fifo_write_to_slot(cb_slot_t *slot, void* data,
|
|
|
|
size_t offset)
|
2004-08-25 00:17:44 +04:00
|
|
|
{
|
2004-08-30 05:25:34 +04:00
|
|
|
return ompi_cb_fifo_write_to_slot(slot->index,data,slot->cb,offset);
|
2004-08-25 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to write pointer to the head of the queue
|
|
|
|
*
|
|
|
|
* @param data Pointer value to write in specified slot (IN)
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
2004-10-12 02:56:46 +04:00
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
2004-08-25 00:17:44 +04:00
|
|
|
* @returncode Slot index to which data is written
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline int ompi_fifo_write_to_head(void *data, ompi_fifo_t
|
2004-08-30 05:25:34 +04:00
|
|
|
*fifo, mca_mpool_base_module_t *fifo_allocator, size_t offset)
|
2004-08-25 00:17:44 +04:00
|
|
|
{
|
|
|
|
int error_code=OMPI_SUCCESS;
|
|
|
|
size_t len_to_allocate;
|
2004-08-27 20:32:09 +04:00
|
|
|
ompi_cb_fifo_wrapper_t *next_ff;
|
2004-08-25 00:17:44 +04:00
|
|
|
bool available;
|
|
|
|
|
|
|
|
/* attempt to write data to head ompi_fifo_cb_fifo_t */
|
2004-08-25 02:25:59 +04:00
|
|
|
error_code=ompi_cb_fifo_write_to_head(data,
|
2004-08-30 05:25:34 +04:00
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo), offset);
|
2004-08-25 00:17:44 +04:00
|
|
|
if( OMPI_CB_ERROR == error_code ) {
|
|
|
|
/*
|
|
|
|
* queue is full
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* mark queue as overflown */
|
|
|
|
fifo->head->cb_overflow=true;
|
|
|
|
|
|
|
|
/* see if next queue is available - while the next queue
|
|
|
|
* has not been emptied, it will be marked as overflowen*/
|
2004-08-25 02:25:59 +04:00
|
|
|
next_ff=(ompi_cb_fifo_wrapper_t *)fifo->head->next_fifo_wrapper;
|
2004-08-27 20:32:09 +04:00
|
|
|
available=!(next_ff->cb_overflow);
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* if next queue not available, allocate new queue */
|
|
|
|
if( !available ) {
|
|
|
|
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t);
|
2004-08-30 05:25:34 +04:00
|
|
|
next_ff=fifo_allocator->mpool_alloc
|
2004-08-25 00:17:44 +04:00
|
|
|
(len_to_allocate,CACHE_LINE_SIZE);
|
2004-08-27 20:32:09 +04:00
|
|
|
if ( NULL == next_ff) {
|
2004-08-25 00:17:44 +04:00
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the circular buffer fifo head structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
error_code=ompi_cb_fifo_init(fifo->head->cb_fifo.size,
|
|
|
|
fifo->head->cb_fifo.lazy_free_frequency,
|
|
|
|
fifo->head->cb_fifo.fifo_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.head_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.tail_memory_locality_index,
|
2004-08-27 20:32:09 +04:00
|
|
|
&(next_ff->cb_fifo),
|
2004-08-30 05:25:34 +04:00
|
|
|
fifo_allocator);
|
2004-08-25 00:17:44 +04:00
|
|
|
if ( OMPI_SUCCESS != error_code ) {
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* finish new element initialization */
|
2004-08-27 20:32:09 +04:00
|
|
|
next_ff->next_fifo_wrapper=fifo->head->next_fifo_wrapper; /* only one
|
2004-08-25 02:25:59 +04:00
|
|
|
element in the
|
|
|
|
link list */
|
2004-08-27 20:32:09 +04:00
|
|
|
next_ff->cb_overflow=false; /* no attempt to overflow the queue */
|
2004-08-25 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset head pointer */
|
2004-08-27 20:32:09 +04:00
|
|
|
fifo->head->next_fifo_wrapper=next_ff;
|
|
|
|
fifo->head=next_ff;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* write data to new head structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
error_code=ompi_cb_fifo_write_to_head(data,
|
2004-08-30 05:25:34 +04:00
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo), offset);
|
2004-08-25 00:17:44 +04:00
|
|
|
if( OMPI_CB_ERROR == error_code ) {
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return */
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reserve slot in the fifo array
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @returncode Slot index to which data is written
|
|
|
|
*
|
2004-10-12 02:56:46 +04:00
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
2004-08-25 00:17:44 +04:00
|
|
|
* @returncode OMPI_CB_ERROR failed to allocate index
|
|
|
|
*
|
|
|
|
*/
|
2004-08-30 05:25:34 +04:00
|
|
|
static inline cb_slot_t ompi_fifo_get_slot(ompi_fifo_t *fifo,
|
|
|
|
mca_mpool_base_module_t *fifo_allocator, size_t offset)
|
|
|
|
{
|
2004-08-25 00:17:44 +04:00
|
|
|
size_t len_to_allocate;
|
2004-08-27 20:32:09 +04:00
|
|
|
volatile ompi_cb_fifo_wrapper_t *next_ff;
|
2004-08-25 00:17:44 +04:00
|
|
|
bool available;
|
|
|
|
cb_slot_t return_params;
|
|
|
|
|
|
|
|
/* attempt to write data to head ompi_fifo_cb_fifo_t */
|
2004-08-25 02:25:59 +04:00
|
|
|
return_params.index=ompi_cb_fifo_get_slot(
|
2004-08-30 05:25:34 +04:00
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo), offset);
|
2004-08-25 00:17:44 +04:00
|
|
|
if( OMPI_CB_ERROR == return_params.index ) {
|
|
|
|
/*
|
|
|
|
* queue is full
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* mark queue as overflown */
|
|
|
|
fifo->head->cb_overflow=true;
|
|
|
|
|
|
|
|
/* see if next queue is available - while the next queue
|
|
|
|
* has not been emptied, it will be marked as overflowen*/
|
|
|
|
next_ff=fifo->head->next_fifo_wrapper;
|
2004-08-27 20:32:09 +04:00
|
|
|
available=!(next_ff->cb_overflow);
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* if next queue not available, allocate new queue */
|
|
|
|
if( !available ) {
|
|
|
|
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t);
|
2004-08-30 05:25:34 +04:00
|
|
|
next_ff=fifo_allocator->mpool_alloc
|
2004-08-25 00:17:44 +04:00
|
|
|
(len_to_allocate,CACHE_LINE_SIZE);
|
2004-08-27 20:32:09 +04:00
|
|
|
if ( NULL == next_ff) {
|
2004-08-25 00:17:44 +04:00
|
|
|
return_params.index=OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the circular buffer fifo head structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
return_params.index=ompi_cb_fifo_init(fifo->head->cb_fifo.size,
|
|
|
|
fifo->head->cb_fifo.lazy_free_frequency,
|
|
|
|
fifo->head->cb_fifo.fifo_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.head_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.tail_memory_locality_index,
|
2004-08-27 20:32:09 +04:00
|
|
|
(ompi_cb_fifo_t *)&(next_ff->cb_fifo),
|
2004-08-30 05:25:34 +04:00
|
|
|
fifo_allocator);
|
2004-08-25 00:17:44 +04:00
|
|
|
if ( OMPI_SUCCESS != return_params.index ) {
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* finish new element initialization */
|
2004-08-27 20:32:09 +04:00
|
|
|
next_ff->next_fifo_wrapper=fifo->head->next_fifo_wrapper; /* only one element in
|
2004-08-25 00:17:44 +04:00
|
|
|
the link list */
|
2004-08-27 20:32:09 +04:00
|
|
|
next_ff->cb_overflow=false; /* no attempt to overflow the queue */
|
2004-08-25 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset head pointer */
|
2004-08-27 20:32:09 +04:00
|
|
|
fifo->head->next_fifo_wrapper=next_ff;
|
|
|
|
fifo->head=next_ff;
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
/* write data to new head structure */
|
2004-08-25 02:25:59 +04:00
|
|
|
return_params.index=ompi_cb_fifo_get_slot(
|
2004-08-30 05:25:34 +04:00
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo), offset);
|
2004-08-25 00:17:44 +04:00
|
|
|
if( OMPI_CB_ERROR == return_params.index ) {
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return */
|
2004-08-25 02:25:59 +04:00
|
|
|
return_params.cb=(ompi_cb_fifo_t *)&(fifo->head->cb_fifo);
|
2004-08-25 00:17:44 +04:00
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to read pointer from the tail of the queue
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
2004-10-12 02:56:46 +04:00
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
|
|
|
* @returncode Pointer - OMPI_CB_FREE indicates no data to read
|
2004-08-25 00:17:44 +04:00
|
|
|
*
|
|
|
|
*/
|
2004-08-30 05:25:34 +04:00
|
|
|
static inline void *ompi_fifo_read_from_tail(ompi_fifo_t *fifo, size_t
|
|
|
|
offset)
|
2004-08-25 00:17:44 +04:00
|
|
|
{
|
|
|
|
/* local parameters */
|
|
|
|
void *return_value;
|
|
|
|
bool queue_empty;
|
|
|
|
|
|
|
|
/* get next element */
|
2004-08-25 02:25:59 +04:00
|
|
|
return_value=ompi_cb_fifo_read_from_tail(
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->tail->cb_fifo),
|
2004-08-30 05:25:34 +04:00
|
|
|
fifo->tail->cb_overflow,&queue_empty, offset);
|
2004-08-27 20:32:09 +04:00
|
|
|
|
2004-08-25 00:17:44 +04:00
|
|
|
/* check to see if need to move on to next cb_fifo in the link list */
|
2004-08-27 20:32:09 +04:00
|
|
|
if( queue_empty ) {
|
2004-08-25 00:17:44 +04:00
|
|
|
/* queue_emptied - move on to next element in fifo */
|
|
|
|
fifo->tail->cb_overflow=false;
|
|
|
|
fifo->tail=fifo->tail->next_fifo_wrapper;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return */
|
|
|
|
return return_value;
|
|
|
|
}
|
2004-11-07 01:00:24 +03:00
|
|
|
/**
|
|
|
|
* Initialize a fifo
|
|
|
|
*
|
|
|
|
* @param size_of_cb_fifo Length of fifo array (IN)
|
|
|
|
*
|
|
|
|
* @param fifo_memory_locality_index Locality index to apply to
|
|
|
|
* the fifo array. Not currently
|
|
|
|
* in use (IN)
|
|
|
|
*
|
|
|
|
* @param tail_memory_locality_index Locality index to apply to the
|
|
|
|
* head control structure. Not
|
|
|
|
* currently in use (IN)
|
|
|
|
*
|
|
|
|
* @param tail_memory_locality_index Locality index to apply to the
|
|
|
|
* tail control structure. Not
|
|
|
|
* currently in use (IN)
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @param memory_allocator Pointer to the memory allocator to use
|
|
|
|
* to allocate memory for this fifo. (IN)
|
|
|
|
*
|
|
|
|
* @returncode Error code
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline int ompi_fifo_init_same_base_addr(int size_of_cb_fifo,
|
|
|
|
int lazy_free_freq, int fifo_memory_locality_index,
|
|
|
|
int head_memory_locality_index, int tail_memory_locality_index,
|
|
|
|
ompi_fifo_t *fifo, mca_mpool_base_module_t *memory_allocator)
|
|
|
|
{
|
|
|
|
int error_code=OMPI_SUCCESS;
|
|
|
|
size_t len_to_allocate;
|
|
|
|
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t);
|
|
|
|
fifo->head=memory_allocator->mpool_alloc(len_to_allocate,CACHE_LINE_SIZE);
|
|
|
|
if ( NULL == fifo->head) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the circular buffer fifo head structure */
|
|
|
|
error_code=ompi_cb_fifo_init_same_base_addr(size_of_cb_fifo,
|
|
|
|
lazy_free_freq, fifo_memory_locality_index,
|
|
|
|
head_memory_locality_index, tail_memory_locality_index,
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo),
|
|
|
|
memory_allocator);
|
|
|
|
if ( OMPI_SUCCESS != error_code ) {
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* finish head initialization */
|
|
|
|
fifo->head->next_fifo_wrapper=
|
|
|
|
(volatile struct ompi_cb_fifo_wrapper_t *)fifo->head; /* only one element
|
|
|
|
in the link list */
|
|
|
|
fifo->head->cb_overflow=false; /* no attempt to overflow the queue */
|
|
|
|
ompi_atomic_unlock(&(fifo->head_lock));
|
|
|
|
ompi_atomic_unlock(&(fifo->tail_lock));
|
|
|
|
|
|
|
|
/* set the tail */
|
|
|
|
fifo->tail=fifo->head;
|
|
|
|
|
|
|
|
/* return */
|
|
|
|
return error_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Write pointer to the specified slot
|
|
|
|
*
|
|
|
|
* @param slot Slot addressing (IN)
|
|
|
|
*
|
|
|
|
* @param data Pointer value to write in specified slot (IN)
|
|
|
|
*
|
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
|
|
|
* @returncode Slot index data written to
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline int ompi_fifo_write_to_slot_same_base_addr(cb_slot_t *slot,
|
|
|
|
void* data, size_t offset)
|
|
|
|
{
|
|
|
|
return ompi_cb_fifo_write_to_slot_same_base_addr(slot->index,data,
|
|
|
|
slot->cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to write pointer to the head of the queue
|
|
|
|
*
|
|
|
|
* @param data Pointer value to write in specified slot (IN)
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @returncode Slot index to which data is written
|
|
|
|
*
|
|
|
|
*/
|
2004-11-16 07:21:30 +03:00
|
|
|
/*
|
2004-11-07 01:00:24 +03:00
|
|
|
static inline int ompi_fifo_write_to_head_same_base_addr(void *data,
|
|
|
|
ompi_fifo_t *fifo, mca_mpool_base_module_t *fifo_allocator)
|
2004-11-16 07:21:30 +03:00
|
|
|
*/
|
|
|
|
#define ompi_fifo_write_to_head_same_base_addr(data, \
|
|
|
|
fifo, fifo_allocator) \
|
|
|
|
({ \
|
|
|
|
int error_code=OMPI_SUCCESS; \
|
|
|
|
size_t len_to_allocate; \
|
|
|
|
ompi_cb_fifo_wrapper_t *next_ff; \
|
|
|
|
bool available; \
|
|
|
|
\
|
|
|
|
/* attempt to write data to head ompi_fifo_cb_fifo_t */ \
|
|
|
|
error_code=ompi_cb_fifo_write_to_head_same_base_addr(data, \
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo)); \
|
|
|
|
if( OMPI_CB_ERROR == error_code ) { \
|
|
|
|
/* \
|
|
|
|
* queue is full \
|
|
|
|
*/ \
|
|
|
|
\
|
|
|
|
/* mark queue as overflown */ \
|
|
|
|
fifo->head->cb_overflow=true; \
|
|
|
|
\
|
|
|
|
/* see if next queue is available - while the next queue \
|
|
|
|
* has not been emptied, it will be marked as overflowen*/ \
|
|
|
|
next_ff=(ompi_cb_fifo_wrapper_t *)fifo->head->next_fifo_wrapper; \
|
|
|
|
available=!(next_ff->cb_overflow); \
|
|
|
|
\
|
|
|
|
/* if next queue not available, allocate new queue */ \
|
|
|
|
if( !available ) { \
|
|
|
|
\
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */ \
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t); \
|
|
|
|
next_ff=fifo_allocator->mpool_alloc \
|
|
|
|
(len_to_allocate,CACHE_LINE_SIZE); \
|
|
|
|
if ( NULL == next_ff) { \
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* initialize the circular buffer fifo head structure */ \
|
|
|
|
error_code=ompi_cb_fifo_init_same_base_addr( \
|
|
|
|
fifo->head->cb_fifo.size, \
|
|
|
|
fifo->head->cb_fifo.lazy_free_frequency, \
|
|
|
|
fifo->head->cb_fifo.fifo_memory_locality_index, \
|
|
|
|
fifo->head->cb_fifo.head_memory_locality_index, \
|
|
|
|
fifo->head->cb_fifo.tail_memory_locality_index, \
|
|
|
|
&(next_ff->cb_fifo), \
|
|
|
|
fifo_allocator); \
|
|
|
|
if ( OMPI_SUCCESS != error_code ) { \
|
|
|
|
return error_code; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* finish new element initialization */ \
|
|
|
|
next_ff->next_fifo_wrapper=fifo->head->next_fifo_wrapper; /* only one \
|
|
|
|
element in the \
|
|
|
|
link list */ \
|
|
|
|
next_ff->cb_overflow=false; /* no attempt to overflow the queue */ \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* reset head pointer */ \
|
|
|
|
fifo->head->next_fifo_wrapper=next_ff; \
|
|
|
|
fifo->head=next_ff; \
|
|
|
|
\
|
|
|
|
/* write data to new head structure */ \
|
|
|
|
error_code=ompi_cb_fifo_write_to_head_same_base_addr(data, \
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo)); \
|
|
|
|
if( OMPI_CB_ERROR == error_code ) { \
|
|
|
|
return error_code; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* return */ \
|
|
|
|
error_code; \
|
|
|
|
}) \
|
2004-11-07 01:00:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reserve slot in the fifo array
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @returncode Slot index to which data is written
|
|
|
|
*
|
|
|
|
* @returncode OMPI_CB_ERROR failed to allocate index
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static inline cb_slot_t ompi_fifo_get_slot_same_base_addr(ompi_fifo_t *fifo,
|
|
|
|
mca_mpool_base_module_t *fifo_allocator)
|
|
|
|
{
|
|
|
|
size_t len_to_allocate;
|
|
|
|
volatile ompi_cb_fifo_wrapper_t *next_ff;
|
|
|
|
bool available;
|
|
|
|
cb_slot_t return_params;
|
|
|
|
|
|
|
|
/* attempt to write data to head ompi_fifo_cb_fifo_t */
|
|
|
|
return_params.index=ompi_cb_fifo_get_slot_same_base_addr(
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo));
|
|
|
|
if( OMPI_CB_ERROR == return_params.index ) {
|
|
|
|
/*
|
|
|
|
* queue is full
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* mark queue as overflown */
|
|
|
|
fifo->head->cb_overflow=true;
|
|
|
|
|
|
|
|
/* see if next queue is available - while the next queue
|
|
|
|
* has not been emptied, it will be marked as overflowen*/
|
|
|
|
next_ff=fifo->head->next_fifo_wrapper;
|
|
|
|
available=!(next_ff->cb_overflow);
|
|
|
|
|
|
|
|
/* if next queue not available, allocate new queue */
|
|
|
|
if( !available ) {
|
|
|
|
|
|
|
|
/* allocate head ompi_cb_fifo_t structure */
|
|
|
|
len_to_allocate=sizeof(ompi_cb_fifo_wrapper_t);
|
|
|
|
next_ff=fifo_allocator->mpool_alloc
|
|
|
|
(len_to_allocate,CACHE_LINE_SIZE);
|
|
|
|
if ( NULL == next_ff) {
|
|
|
|
return_params.index=OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the circular buffer fifo head structure */
|
|
|
|
return_params.index=ompi_cb_fifo_init_same_base_addr(
|
|
|
|
fifo->head->cb_fifo.size,
|
|
|
|
fifo->head->cb_fifo.lazy_free_frequency,
|
|
|
|
fifo->head->cb_fifo.fifo_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.head_memory_locality_index,
|
|
|
|
fifo->head->cb_fifo.tail_memory_locality_index,
|
|
|
|
(ompi_cb_fifo_t *)&(next_ff->cb_fifo),
|
|
|
|
fifo_allocator);
|
|
|
|
if ( OMPI_SUCCESS != return_params.index ) {
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* finish new element initialization */
|
|
|
|
next_ff->next_fifo_wrapper=fifo->head->next_fifo_wrapper; /* only one element in
|
|
|
|
the link list */
|
|
|
|
next_ff->cb_overflow=false; /* no attempt to overflow the queue */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset head pointer */
|
|
|
|
fifo->head->next_fifo_wrapper=next_ff;
|
|
|
|
fifo->head=next_ff;
|
|
|
|
|
|
|
|
/* write data to new head structure */
|
|
|
|
return_params.index=ompi_cb_fifo_get_slot_same_base_addr(
|
|
|
|
(ompi_cb_fifo_t *)&(fifo->head->cb_fifo));
|
|
|
|
if( OMPI_CB_ERROR == return_params.index ) {
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return */
|
|
|
|
return_params.cb=(ompi_cb_fifo_t *)&(fifo->head->cb_fifo);
|
|
|
|
return return_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to read pointer from the tail of the queue
|
|
|
|
*
|
|
|
|
* @param fifo Pointer to data structure defining this fifo (IN)
|
|
|
|
*
|
|
|
|
* @param offset Offset relative to base of the memory segement (IN)
|
|
|
|
*
|
|
|
|
* @returncode Pointer - OMPI_CB_FREE indicates no data to read
|
|
|
|
*
|
|
|
|
*/
|
2004-11-17 22:25:22 +03:00
|
|
|
/*
|
2004-11-07 01:00:24 +03:00
|
|
|
static inline void *ompi_fifo_read_from_tail_same_base_addr(
|
|
|
|
ompi_fifo_t *fifo)
|
2004-11-17 22:25:22 +03:00
|
|
|
*/
|
|
|
|
#define ompi_fifo_read_from_tail_same_base_addr( fifo ) \
|
|
|
|
({ \
|
|
|
|
/* local parameters */ \
|
|
|
|
void *return_value; \
|
|
|
|
bool queue_empty,flush_entries_read; \
|
|
|
|
ompi_cb_fifo_t *cb_fifo; \
|
|
|
|
\
|
|
|
|
/* get next element */ \
|
|
|
|
cb_fifo=(ompi_cb_fifo_t *)&(fifo->tail->cb_fifo); \
|
|
|
|
flush_entries_read=fifo->tail->cb_overflow; \
|
|
|
|
return_value=ompi_cb_fifo_read_from_tail_same_base_addr(cb_fifo, \
|
|
|
|
flush_entries_read,&queue_empty); \
|
|
|
|
\
|
|
|
|
/* check to see if need to move on to next cb_fifo in the link list */ \
|
|
|
|
if( queue_empty ) { \
|
|
|
|
/* queue_emptied - move on to next element in fifo */ \
|
|
|
|
fifo->tail->cb_overflow=false; \
|
|
|
|
fifo->tail=fifo->tail->next_fifo_wrapper; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
/* return */ \
|
|
|
|
return_value; \
|
|
|
|
})
|
2004-08-25 00:17:44 +04:00
|
|
|
|
|
|
|
#endif /* !_OMPI_FIFO */
|