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