Add memory barrier in single-node-reclaim case. Improve comments.
authorRobert Haas <rhaas@postgresql.org>
Thu, 2 Aug 2012 17:59:24 +0000 (17:59 +0000)
committerRobert Haas <rhaas@postgresql.org>
Thu, 2 Aug 2012 17:59:24 +0000 (17:59 +0000)
src/backend/utils/hash/chash.c

index 4168f06fbd6e575701726231f5f94e192b825dcb..2da735ab4cdd913e1d54ec99554e82e684e73106 100644 (file)
@@ -922,16 +922,28 @@ CHashAllocate(CHashTable table)
                        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;