pg_read_barrier_depends();
fhead = n->un.gcnext;
- /*
- * Prepend everything except the one node we've saved to satisfy
- * this allocation to the free list. If the free list is empty,
- * we needn't update the list any further; otherwise, we've got
- * to adjust the next-pointer in the last of the reclaimed nodes.
- */
if (CHashPtrIsInvalid(fhead))
+ {
+ /*
+ * We have reclaimed exactly node, so there's nothing to put
+ * back on the free list. In this case (only) we need a
+ * memory barrier, because the reads above must complete
+ * before we overwrite n->un.gcnext with a new hashcode.
+ * (This is only needed when we reclaim exactly one node,
+ * because in any other case we'll do a compare-and-swap
+ * before returning, which implies a full barrier.)
+ */
+ pg_memory_barrier();
CHashTableIncrementStatistic(table, CHS_GC_Reclaim_Skipped);
+ }
else if (__sync_bool_compare_and_swap(fh, InvalidCHashPtr, fhead))
+ {
+ /*
+ * Our free list is empty, and we've succesfully pushed the
+ * reclaimed nodes onto it. So we're done.
+ */
CHashTableIncrementStatistic(table, CHS_GC_Reclaim_Fast);
+ }
else
{
CHashPtr fcurrent;