If we fail to allocate from a non-empty freelist, retry same list.
authorRobert Haas <rhaas@postgresql.org>
Wed, 1 Aug 2012 20:37:28 +0000 (20:37 +0000)
committerRobert Haas <rhaas@postgresql.org>
Mon, 13 Oct 2014 17:14:19 +0000 (13:14 -0400)
src/backend/utils/hash/chash.c

index 40abd53c482f30f7dddb4f12a7ad38f4b332086d..1fc507af1819be7efef6d47ecba0a59df0db81a9 100644 (file)
@@ -869,12 +869,17 @@ CHashAllocate(CHashTable table)
         * 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);
 
@@ -887,6 +892,7 @@ CHashAllocate(CHashTable table)
            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. */