* means that we can't allow any element that is currently on this
* freelist to be allocated, marked as garbage, garbage collected,
* and returned back to this freelist before we finish the CAS.
+ *
+ * If we attempt to pop the free-list and fail, we retry immediately
+ * with the same free-list. This reduces the frequency with which
+ * we're obliged to update our hazard pointers, which is a material
+ * savings due to the associated memory barrier.
*/
b = &table->freelist[f_current];
MyProc->hazard[0] = b;
pg_memory_barrier();
new = *b;
- if (!CHashPtrIsInvalid(new))
+ while (!CHashPtrIsInvalid(new))
{
CHashNode *n = CHashTableGetNode(table, new);
if (__sync_bool_compare_and_swap(b, new, n->un.gcnext))
return new;
table->stats.s_allocate_pop_fail++;
+ new = *b;
}
/* If next garbage list is non-empty, empty it via compare-and-swap. */