|
12 | 12 | * All rights reserved. |
13 | 13 | * Copyright (c) 2007 Voltaire All rights reserved. |
14 | 14 | * Copyright (c) 2010 IBM Corporation. All rights reserved. |
15 | | - * Copyright (c) 2014 Los Alamos National Security, LLC. All rights |
| 15 | + * Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights |
16 | 16 | * reseved. |
17 | 17 | * $COPYRIGHT$ |
18 | 18 | * |
|
25 | 25 | #define OPAL_LIFO_H_HAS_BEEN_INCLUDED |
26 | 26 |
|
27 | 27 | #include "opal_config.h" |
| 28 | +#include <time.h> |
28 | 29 | #include "opal/class/opal_list.h" |
29 | 30 |
|
30 | 31 | #include "opal/sys/atomic.h" |
@@ -180,6 +181,52 @@ static inline opal_list_item_t *opal_lifo_push_atomic (opal_lifo_t *lifo, |
180 | 181 | } while (1); |
181 | 182 | } |
182 | 183 |
|
| 184 | +#if OPAL_HAVE_ATOMIC_LLSC_PTR |
| 185 | + |
| 186 | +static inline void _opal_lifo_release_cpu (void) |
| 187 | +{ |
| 188 | + /* NTH: there are many ways to cause the current thread to be suspended. This one |
| 189 | + * should work well in most cases. Another approach would be to use poll (NULL, 0, ) but |
| 190 | + * the interval will be forced to be in ms (instead of ns or us). Note that there |
| 191 | + * is a performance improvement for the lifo test when this call is made on detection |
| 192 | + * of contention but it may not translate into actually MPI or application performance |
| 193 | + * improvements. */ |
| 194 | + static struct timespec interval = { .tv_sec = 0, .tv_nsec = 100 }; |
| 195 | + nanosleep (&interval, NULL); |
| 196 | +} |
| 197 | + |
| 198 | +/* Retrieve one element from the LIFO. If we reach the ghost element then the LIFO |
| 199 | + * is empty so we return NULL. |
| 200 | + */ |
| 201 | +static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo) |
| 202 | +{ |
| 203 | + opal_list_item_t *item, *next; |
| 204 | + int attempt = 0; |
| 205 | + |
| 206 | + do { |
| 207 | + if (++attempt == 5) { |
| 208 | + /* deliberatly suspend this thread to allow other threads to run. this should |
| 209 | + * only occur during periods of contention on the lifo. */ |
| 210 | + _opal_lifo_release_cpu (); |
| 211 | + attempt = 0; |
| 212 | + } |
| 213 | + |
| 214 | + item = (opal_list_item_t *) opal_atomic_ll_ptr (&lifo->opal_lifo_head.data.item); |
| 215 | + if (&lifo->opal_lifo_ghost == item) { |
| 216 | + return NULL; |
| 217 | + } |
| 218 | + |
| 219 | + next = (opal_list_item_t *) item->opal_list_next; |
| 220 | + } while (!opal_atomic_sc_ptr (&lifo->opal_lifo_head.data.item, next)); |
| 221 | + |
| 222 | + opal_atomic_wmb (); |
| 223 | + |
| 224 | + item->opal_list_next = NULL; |
| 225 | + return item; |
| 226 | +} |
| 227 | + |
| 228 | +#else |
| 229 | + |
183 | 230 | /* Retrieve one element from the LIFO. If we reach the ghost element then the LIFO |
184 | 231 | * is empty so we return NULL. |
185 | 232 | */ |
@@ -216,6 +263,8 @@ static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo) |
216 | 263 | return item; |
217 | 264 | } |
218 | 265 |
|
| 266 | +#endif /* OPAL_HAVE_ATOMIC_LLSC_PTR */ |
| 267 | + |
219 | 268 | #endif |
220 | 269 |
|
221 | 270 | /* single-threaded versions of the lifo functions */ |
|
0 commit comments