1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2006 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OPAL_FREE_LIST_H
#define OPAL_FREE_LIST_H
#include "opal_config.h"
#include "opal/class/opal_list.h"
#include "opal/threads/condition.h"
#include "opal/constants.h"
#include "opal/prefetch.h"
BEGIN_C_DECLS
struct opal_free_list_t
{
opal_list_t super;
size_t fl_max_to_alloc;
size_t fl_num_allocated;
size_t fl_num_per_alloc;
size_t fl_num_waiting;
size_t fl_elem_size;
opal_class_t* fl_elem_class;
opal_mutex_t fl_lock;
opal_condition_t fl_condition;
opal_list_t fl_allocations;
};
typedef struct opal_free_list_t opal_free_list_t;
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_free_list_t);
struct opal_free_list_item_t
{
opal_list_item_t super;
};
typedef struct opal_free_list_item_t opal_free_list_item_t;
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_free_list_item_t);
/**
* Initialize a free list.
*
* @param free_list (IN) Free list.
* @param element_size (IN) Size of each element.
* @param element_class (IN) opal_class_t of element - used to initialize allocated elements.
* @param num_elements_to_alloc Initial number of elements to allocate.
* @param max_elements_to_alloc Maximum number of elements to allocate.
* @param num_elements_per_alloc Number of elements to grow by per allocation.
*/
OPAL_DECLSPEC int opal_free_list_init(
opal_free_list_t *free_list,
size_t element_size,
opal_class_t* element_class,
int num_elements_to_alloc,
int max_elements_to_alloc,
int num_elements_per_alloc);
OPAL_DECLSPEC int opal_free_list_grow(opal_free_list_t* flist, size_t num_elements) __opal_attribute_nonnull__(1);
/**
* Attemp to obtain an item from a free list.
*
* @param fl (IN) Free list.
* @param item (OUT) Allocated item.
* @param rc (OUT) OPAL_SUCCESS or error status on failure.
*
* If the requested item is not available the free list is grown to
* accomodate the request - unless the max number of allocations has
* been reached. If this is the case - an out of resource error is
* returned to the caller.
*/
#define OPAL_FREE_LIST_GET(fl, item, rc) \
{ \
if(opal_using_threads()) { \
opal_mutex_lock(&((fl)->fl_lock)); \
item = (opal_free_list_item_t*) \
opal_list_remove_first(&((fl)->super)); \
if( OPAL_UNLIKELY(NULL == item) ) { \
opal_free_list_grow((fl), (fl)->fl_num_per_alloc); \
item = (opal_free_list_item_t*) \
opal_list_remove_first(&((fl)->super)); \
} \
opal_mutex_unlock(&((fl)->fl_lock)); \
} else { \
item = (opal_free_list_item_t*) \
opal_list_remove_first(&((fl)->super)); \
if( OPAL_UNLIKELY(NULL == item) ) { \
opal_free_list_grow((fl), (fl)->fl_num_per_alloc); \
item = (opal_free_list_item_t*) \
opal_list_remove_first(&((fl)->super)); \
} \
} \
rc = (NULL == item) ? OPAL_ERR_TEMP_OUT_OF_RESOURCE : OPAL_SUCCESS; \
}
/**
* Blocking call to obtain an item from a free list.
*
* @param fl (IN) Free list.
* @param item (OUT) Allocated item.
* @param rc (OUT) OPAL_SUCCESS or error status on failure.
*
* If the requested item is not available the free list is grown to
* accomodate the request - unless the max number of allocations has
* been reached. In this case the caller is blocked until an item
* is returned to the list.
*/
#define OPAL_FREE_LIST_WAIT(fl, item, rc) \
do { \
OPAL_THREAD_LOCK(&((fl)->fl_lock)); \
while( NULL == (item = (opal_free_list_item_t*) opal_list_remove_first(&((fl)->super))) ) { \
if( OPAL_LIKELY((fl)->fl_max_to_alloc <= (fl)->fl_num_allocated) ) { \
(fl)->fl_num_waiting++; \
opal_condition_wait(&((fl)->fl_condition), &((fl)->fl_lock)); \
(fl)->fl_num_waiting--; \
} else { \
opal_free_list_grow((fl), (fl)->fl_num_per_alloc); \
} \
} \
OPAL_THREAD_UNLOCK(&((fl)->fl_lock)); \
rc = OPAL_SUCCESS; \
} while(0)
/**
* Return an item to a free list.
*
* @param fl (IN) Free list.
* @param item (OUT) Allocated item.
*
*/
#define OPAL_FREE_LIST_RETURN(fl, item) \
do { \
OPAL_THREAD_LOCK(&(fl)->fl_lock); \
opal_list_prepend(&((fl)->super), ((opal_list_item_t*) item)); \
if( OPAL_UNLIKELY((fl)->fl_num_waiting > 0) ) { \
opal_condition_signal(&((fl)->fl_condition)); \
} \
OPAL_THREAD_UNLOCK(&(fl)->fl_lock); \
} while(0)
END_C_DECLS
#endif
|