static bool swap_heap_region_head(struct PupHeap *heap, struct PupHeapRegion *old_region, struct PupHeapRegion *new_region) { return AO_compare_and_swap((AO_t *)&heap->region_list, (AO_t)old_region, (AO_t)new_region); }
static bool swap_thread_list_head(struct PupHeap *heap, struct PupThreadInfo *old_head, struct PupThreadInfo *new_head) { return AO_compare_and_swap((AO_t *)&heap->thread_list, (AO_t)old_head, (AO_t)new_head); }
AO_t * AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) { unsigned i; int j = 0; AO_t first; AO_t * first_ptr; AO_t next; retry: first = AO_load(list); if (0 == first) return 0; /* Insert first into aux black list. */ /* This may spin if more than AO_BL_SIZE removals using auxiliary */ /* structure a are currently in progress. */ for (i = 0; ; ) { if (PRECHECK(a -> AO_stack_bl[i]) AO_compare_and_swap(a->AO_stack_bl+i, 0, first)) break; ++i; if ( i >= AO_BL_SIZE ) { i = 0; AO_pause(++j); } } assert(i < AO_BL_SIZE); assert(a -> AO_stack_bl[i] == first); /* First is on the auxiliary black list. It may be removed by */ /* another thread before we get to it, but a new insertion of x */ /* cannot be started here. */ /* Only we can remove it from the black list. */ /* We need to make sure that first is still the first entry on the */ /* list. Otherwise it's possible that a reinsertion of it was */ /* already started before we added the black list entry. */ AO_nop_full(); /* TODO: Suboptimal on x86 */ # if defined(__alpha__) && (__GNUC__ == 4) if (first != AO_load(list)) /* Workaround __builtin_expect bug found in */ /* gcc-4.6.3/alpha causing test_stack failure. */ # else if (AO_EXPECT_FALSE(first != AO_load(list))) # endif { AO_store_release(a->AO_stack_bl+i, 0); goto retry; } first_ptr = AO_REAL_NEXT_PTR(first); next = AO_load(first_ptr); # if defined(__alpha__) && (__GNUC__ == 4) if (!AO_compare_and_swap_release(list, first, next)) # else if (AO_EXPECT_FALSE(!AO_compare_and_swap_release(list, first, next))) # endif { AO_store_release(a->AO_stack_bl+i, 0); goto retry; } assert(*list != first); /* Since we never insert an entry on the black list, this cannot have */ /* succeeded unless first remained on the list while we were running. */ /* Thus its next link cannot have changed out from under us, and we */ /* removed exactly one entry and preserved the rest of the list. */ /* Note that it is quite possible that an additional entry was */ /* inserted and removed while we were running; this is OK since the */ /* part of the list following first must have remained unchanged, and */ /* first must again have been at the head of the list when the */ /* compare_and_swap succeeded. */ AO_store_release(a->AO_stack_bl+i, 0); return first_ptr; }