1212 * All rights reserved.
1313 * Copyright (c) 2010 IBM Corporation. All rights reserved.
1414 * 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
1616 * reserved.
1717 * $COPYRIGHT$
1818 *
@@ -146,6 +146,7 @@ OPAL_DECLSPEC int opal_free_list_init (opal_free_list_t *free_list,
146146 *
147147 * @param flist (IN) Free list to grow
148148 * @param num_elements (IN) Number of elements to add
149+ * @param item_out (OUT) Location to store new free list item (can be NULL)
149150 *
150151 * @returns OPAL_SUCCESS if any elements were added
151152 * @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,
155156 * that may be accessed by multiple threads simultaneously. Note: this is an
156157 * internal function that will be used when needed by opal_free_list_get* and
157158 * 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).
158165 */
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 );
160167
161168/**
162169 * 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
195202
196203 if (OPAL_UNLIKELY (NULL == item )) {
197204 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 );
199206 opal_mutex_unlock (& flist -> fl_lock );
200- item = (opal_free_list_item_t * ) opal_lifo_pop_atomic (& flist -> super );
201207 }
202208
203209 return item ;
@@ -209,8 +215,7 @@ static inline opal_free_list_item_t *opal_free_list_get_st (opal_free_list_t *fl
209215 (opal_free_list_item_t * ) opal_lifo_pop_st (& flist -> super );
210216
211217 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 );
214219 }
215220
216221 return item ;
@@ -253,7 +258,7 @@ static inline opal_free_list_item_t *opal_free_list_wait_mt (opal_free_list_t *f
253258 while (NULL == item ) {
254259 if (!opal_mutex_trylock (& fl -> fl_lock )) {
255260 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 )) {
257262 fl -> fl_num_waiting ++ ;
258263 opal_condition_wait (& fl -> fl_condition , & fl -> fl_lock );
259264 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
274279 opal_mutex_lock (& fl -> fl_lock );
275280 }
276281 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+ }
278285 }
279286
280287 return item ;
@@ -287,12 +294,13 @@ static inline opal_free_list_item_t *opal_free_list_wait_st (opal_free_list_t *f
287294
288295 while (NULL == item ) {
289296 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 )) {
291298 /* try to make progress */
292299 opal_progress ();
293300 }
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+ }
296304 }
297305
298306 return item ;
0 commit comments