This source file includes following definitions.
- opal_update_counted_pointer
- opal_read_counted_pointer
- _opal_lifo_release_cpu
- opal_lifo_is_empty
- opal_lifo_push_atomic
- opal_lifo_pop_atomic
- opal_lifo_push_atomic
- opal_lifo_pop_atomic
- opal_lifo_pop_atomic
- opal_lifo_push_st
- opal_lifo_pop_st
- opal_lifo_push
- opal_lifo_pop
   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 #ifndef OPAL_LIFO_H_HAS_BEEN_INCLUDED
  27 #define OPAL_LIFO_H_HAS_BEEN_INCLUDED
  28 
  29 #include "opal_config.h"
  30 #include <time.h>
  31 #include "opal/class/opal_list.h"
  32 
  33 #include "opal/sys/atomic.h"
  34 #include "opal/threads/mutex.h"
  35 
  36 BEGIN_C_DECLS
  37 
  38 
  39 #if !defined(OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128)
  40 #define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 0
  41 #endif
  42 
  43 
  44 
  45 
  46 union opal_counted_pointer_t {
  47     struct {
  48         
  49         uint64_t counter;
  50         
  51         volatile opal_atomic_intptr_t item;
  52     } data;
  53 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 && HAVE_OPAL_INT128_T
  54     
  55 
  56     opal_atomic_int128_t atomic_value;
  57     opal_int128_t value;
  58 #endif
  59 };
  60 typedef union opal_counted_pointer_t opal_counted_pointer_t;
  61 
  62 
  63 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
  64 
  65 
  66 
  67 
  68 
  69 static inline bool opal_update_counted_pointer (volatile opal_counted_pointer_t * volatile addr, opal_counted_pointer_t *old,
  70                                                 opal_list_item_t *item)
  71 {
  72     opal_counted_pointer_t new_p;
  73     new_p.data.item = (intptr_t) item;
  74     new_p.data.counter = old->data.counter + 1;
  75     return opal_atomic_compare_exchange_strong_128 (&addr->atomic_value, &old->value, new_p.value);
  76 }
  77 
  78 __opal_attribute_always_inline__
  79 static inline void opal_read_counted_pointer (volatile opal_counted_pointer_t * volatile addr, opal_counted_pointer_t *value)
  80 {
  81     
  82     value->data.counter = addr->data.counter;
  83     opal_atomic_rmb ();
  84     value->data.item = addr->data.item;
  85 }
  86 
  87 #endif
  88 
  89 
  90 
  91 
  92 static inline void _opal_lifo_release_cpu (void)
  93 {
  94     
  95 
  96 
  97 
  98 
  99 
 100     static struct timespec interval = { .tv_sec = 0, .tv_nsec = 100 };
 101     nanosleep (&interval, NULL);
 102 }
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 struct opal_lifo_t {
 115     opal_object_t super;
 116 
 117     
 118     volatile opal_counted_pointer_t opal_lifo_head;
 119 
 120     
 121     opal_list_item_t opal_lifo_ghost;
 122 };
 123 
 124 typedef struct opal_lifo_t opal_lifo_t;
 125 
 126 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_lifo_t);
 127 
 128 
 129 
 130 
 131 
 132 
 133 static inline bool opal_lifo_is_empty( opal_lifo_t* lifo )
 134 {
 135     return (opal_list_item_t *) lifo->opal_lifo_head.data.item == &lifo->opal_lifo_ghost;
 136 }
 137 
 138 
 139 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
 140 
 141 
 142 
 143 
 144 
 145 static inline opal_list_item_t *opal_lifo_push_atomic (opal_lifo_t *lifo,
 146                                                        opal_list_item_t *item)
 147 {
 148     opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
 149 
 150     do {
 151         item->opal_list_next = next;
 152         opal_atomic_wmb ();
 153 
 154         
 155         if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, (intptr_t *) &next, (intptr_t) item)) {
 156             return next;
 157         }
 158         
 159     } while (1);
 160 }
 161 
 162 
 163 
 164 
 165 static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
 166 {
 167     opal_counted_pointer_t old_head;
 168     opal_list_item_t *item;
 169 
 170     opal_read_counted_pointer (&lifo->opal_lifo_head, &old_head);
 171 
 172     do {
 173         item = (opal_list_item_t *) old_head.data.item;
 174         if (item == &lifo->opal_lifo_ghost) {
 175             return NULL;
 176         }
 177 
 178         if (opal_update_counted_pointer (&lifo->opal_lifo_head, &old_head,
 179                                          (opal_list_item_t *) item->opal_list_next)) {
 180             opal_atomic_wmb ();
 181             item->opal_list_next = NULL;
 182             return item;
 183         }
 184     } while (1);
 185 }
 186 
 187 #else
 188 
 189 
 190 
 191 
 192 
 193 static inline opal_list_item_t *opal_lifo_push_atomic (opal_lifo_t *lifo,
 194                                                        opal_list_item_t *item)
 195 {
 196     opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
 197 
 198     
 199     item->item_free = 1;
 200 
 201     do {
 202         item->opal_list_next = next;
 203         opal_atomic_wmb();
 204         if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, (intptr_t *) &next, (intptr_t) item)) {
 205             opal_atomic_wmb ();
 206             
 207             item->item_free = 0;
 208             return next;
 209         }
 210         
 211     } while (1);
 212 }
 213 
 214 #if OPAL_HAVE_ATOMIC_LLSC_PTR
 215 
 216 
 217 
 218 
 219 static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
 220 {
 221     register opal_list_item_t *item, *next;
 222     int attempt = 0, ret;
 223 
 224     do {
 225         if (++attempt == 5) {
 226             
 227 
 228             _opal_lifo_release_cpu ();
 229             attempt = 0;
 230         }
 231 
 232         opal_atomic_ll_ptr(&lifo->opal_lifo_head.data.item, item);
 233         if (&lifo->opal_lifo_ghost == item) {
 234             return NULL;
 235         }
 236 
 237         next = (opal_list_item_t *) item->opal_list_next;
 238         opal_atomic_sc_ptr(&lifo->opal_lifo_head.data.item, next, ret);
 239     } while (!ret);
 240 
 241     opal_atomic_wmb ();
 242 
 243     item->opal_list_next = NULL;
 244     return item;
 245 }
 246 
 247 #else
 248 
 249 
 250 
 251 
 252 static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
 253 {
 254     opal_list_item_t *item, *head, *ghost = &lifo->opal_lifo_ghost;
 255 
 256     while ((item=(opal_list_item_t *)lifo->opal_lifo_head.data.item) != ghost) {
 257         
 258         if (opal_atomic_swap_32((opal_atomic_int32_t *) &item->item_free, 1)) {
 259             continue;
 260         }
 261 
 262         opal_atomic_wmb ();
 263 
 264         head = item;
 265         
 266         if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, (intptr_t *) &head,
 267                                                      (intptr_t) item->opal_list_next)) {
 268             break;
 269         }
 270 
 271         
 272         item->item_free = 0;
 273         item = head;
 274 
 275         
 276     }
 277 
 278     if (item == &lifo->opal_lifo_ghost) {
 279         return NULL;
 280     }
 281 
 282     opal_atomic_wmb ();
 283 
 284     item->opal_list_next = NULL;
 285     return item;
 286 }
 287 
 288 #endif 
 289 
 290 #endif
 291 
 292 
 293 static inline opal_list_item_t *opal_lifo_push_st (opal_lifo_t *lifo,
 294                                                    opal_list_item_t *item)
 295 {
 296     item->opal_list_next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
 297     item->item_free = 0;
 298     lifo->opal_lifo_head.data.item = (intptr_t) item;
 299     return (opal_list_item_t *) item->opal_list_next;
 300 }
 301 
 302 static inline opal_list_item_t *opal_lifo_pop_st (opal_lifo_t *lifo)
 303 {
 304     opal_list_item_t *item;
 305     item = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
 306     lifo->opal_lifo_head.data.item = (intptr_t) item->opal_list_next;
 307     if (item == &lifo->opal_lifo_ghost) {
 308         return NULL;
 309     }
 310 
 311     item->opal_list_next = NULL;
 312     item->item_free = 1;
 313     return item;
 314 }
 315 
 316 
 317 static inline opal_list_item_t *opal_lifo_push (opal_lifo_t *lifo,
 318                                                 opal_list_item_t *item)
 319 {
 320     if (opal_using_threads ()) {
 321         return opal_lifo_push_atomic (lifo, item);
 322     }
 323 
 324     return opal_lifo_push_st (lifo, item);
 325 }
 326 
 327 static inline opal_list_item_t *opal_lifo_pop (opal_lifo_t *lifo)
 328 {
 329     if (opal_using_threads ()) {
 330         return opal_lifo_pop_atomic (lifo);
 331     }
 332 
 333     return opal_lifo_pop_st (lifo);
 334 }
 335 
 336 END_C_DECLS
 337 
 338 #endif