12
12
* All rights reserved.
13
13
* Copyright (c) 2010 IBM Corporation. All rights reserved.
14
14
* Copyright (c) 2010-2015 Cisco Systems, Inc. All rights reserved.
15
- * Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
15
+ * Copyright (c) 2014-2018 Los Alamos National Security, LLC. All rights
16
16
* reserved.
17
17
* $COPYRIGHT$
18
18
*
@@ -146,6 +146,7 @@ OPAL_DECLSPEC int opal_free_list_init (opal_free_list_t *free_list,
146
146
*
147
147
* @param flist (IN) Free list to grow
148
148
* @param num_elements (IN) Number of elements to add
149
+ * @param item_out (OUT) Location to store new free list item (can be NULL)
149
150
*
150
151
* @returns OPAL_SUCCESS if any elements were added
151
152
* @returns OPAL_ERR_OUT_OF_RESOURCE if no elements could be added
@@ -155,8 +156,14 @@ OPAL_DECLSPEC int opal_free_list_init (opal_free_list_t *free_list,
155
156
* that may be accessed by multiple threads simultaneously. Note: this is an
156
157
* internal function that will be used when needed by opal_free_list_get* and
157
158
* opal_free_list_wait*.
159
+ *
160
+ * The item_out parameter can be used to ensure that the thread calling this
161
+ * function always gets a free list item if the list is successfully grown.
162
+ * This eliminates a race condition with code that simply calls free_list_get
163
+ * and assumes NULL is an out of memory condition (which it wasn't necessarily
164
+ * before this parameter was added).
158
165
*/
159
- OPAL_DECLSPEC int opal_free_list_grow_st (opal_free_list_t * flist , size_t num_elements );
166
+ OPAL_DECLSPEC int opal_free_list_grow_st (opal_free_list_t * flist , size_t num_elements , opal_free_list_item_t * * item_out );
160
167
161
168
/**
162
169
* Grow the free list to be at least size elements.
@@ -195,9 +202,8 @@ static inline opal_free_list_item_t *opal_free_list_get_mt (opal_free_list_t *fl
195
202
196
203
if (OPAL_UNLIKELY (NULL == item )) {
197
204
opal_mutex_lock (& flist -> fl_lock );
198
- opal_free_list_grow_st (flist , flist -> fl_num_per_alloc );
205
+ opal_free_list_grow_st (flist , flist -> fl_num_per_alloc , & item );
199
206
opal_mutex_unlock (& flist -> fl_lock );
200
- item = (opal_free_list_item_t * ) opal_lifo_pop_atomic (& flist -> super );
201
207
}
202
208
203
209
return item ;
@@ -209,8 +215,7 @@ static inline opal_free_list_item_t *opal_free_list_get_st (opal_free_list_t *fl
209
215
(opal_free_list_item_t * ) opal_lifo_pop_st (& flist -> super );
210
216
211
217
if (OPAL_UNLIKELY (NULL == item )) {
212
- opal_free_list_grow_st (flist , flist -> fl_num_per_alloc );
213
- item = (opal_free_list_item_t * ) opal_lifo_pop_atomic (& flist -> super );
218
+ opal_free_list_grow_st (flist , flist -> fl_num_per_alloc , & item );
214
219
}
215
220
216
221
return item ;
@@ -253,7 +258,7 @@ static inline opal_free_list_item_t *opal_free_list_wait_mt (opal_free_list_t *f
253
258
while (NULL == item ) {
254
259
if (!opal_mutex_trylock (& fl -> fl_lock )) {
255
260
if (fl -> fl_max_to_alloc <= fl -> fl_num_allocated ||
256
- OPAL_SUCCESS != opal_free_list_grow_st (fl , fl -> fl_num_per_alloc )) {
261
+ OPAL_SUCCESS != opal_free_list_grow_st (fl , fl -> fl_num_per_alloc , & item )) {
257
262
fl -> fl_num_waiting ++ ;
258
263
opal_condition_wait (& fl -> fl_condition , & fl -> fl_lock );
259
264
fl -> fl_num_waiting -- ;
@@ -274,7 +279,9 @@ static inline opal_free_list_item_t *opal_free_list_wait_mt (opal_free_list_t *f
274
279
opal_mutex_lock (& fl -> fl_lock );
275
280
}
276
281
opal_mutex_unlock (& fl -> fl_lock );
277
- item = (opal_free_list_item_t * ) opal_lifo_pop_atomic (& fl -> super );
282
+ if (NULL == item ) {
283
+ item = (opal_free_list_item_t * ) opal_lifo_pop_atomic (& fl -> super );
284
+ }
278
285
}
279
286
280
287
return item ;
@@ -287,12 +294,13 @@ static inline opal_free_list_item_t *opal_free_list_wait_st (opal_free_list_t *f
287
294
288
295
while (NULL == item ) {
289
296
if (fl -> fl_max_to_alloc <= fl -> fl_num_allocated ||
290
- OPAL_SUCCESS != opal_free_list_grow_st (fl , fl -> fl_num_per_alloc )) {
297
+ OPAL_SUCCESS != opal_free_list_grow_st (fl , fl -> fl_num_per_alloc , & item )) {
291
298
/* try to make progress */
292
299
opal_progress ();
293
300
}
294
-
295
- item = (opal_free_list_item_t * ) opal_lifo_pop (& fl -> super );
301
+ if (NULL == item ) {
302
+ item = (opal_free_list_item_t * ) opal_lifo_pop (& fl -> super );
303
+ }
296
304
}
297
305
298
306
return item ;
0 commit comments