[pypy-commit] stmgc hashtable-iter: maybe found a simpler and better way

arigo noreply at buildbot.pypy.org
Sun Feb 1 00:27:14 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: hashtable-iter
Changeset: r1599:274a3dfec8ad
Date: 2015-02-01 00:27 +0100
http://bitbucket.org/pypy/stmgc/changeset/274a3dfec8ad/

Log:	maybe found a simpler and better way

diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c
--- a/c7/stm/hashtable.c
+++ b/c7/stm/hashtable.c
@@ -25,6 +25,10 @@
 transaction rather than the modifying transaction, which is probably
 what we want.
 
+XXX NO: when creating new key/value objects, we should copy the read
+marker from the hashtableobj to the new key/value object.  I *think*
+this gives a correct and better result XXX
+
 
 Implementation
 --------------
@@ -231,7 +235,16 @@
             perturb >>= PERTURB_SHIFT;
         }
     }
-    /* here, we didn't find the 'entry' with the correct index. */
+    /* here, we didn't find the 'entry' with the correct index.  Note
+       that even if the same 'table' is modified or resized by other
+       threads concurrently, any new item found from a race condition
+       would anyway contain NULL in the present segment (ensured by
+       the first write_fence() below).  If the 'table' grows an entry
+       just after we checked above, then we go ahead and lock the
+       table; but after we get the lock, we will notice the new entry
+       (ensured by the second write_fence() below) and restart the
+       whole process.
+     */
 
     intptr_t rc = VOLATILE_TABLE(table)->resize_counter;
     bool rc_must_be_negative = false;
@@ -347,9 +360,25 @@
          */
         int j, my_segment = STM_SEGMENT->segment_num;
         for (j = 1; j <= NB_SEGMENTS; j++) {
-            if (j != my_segment) {
-                if (was_read_remote(get_segment_base(j), hashtableobj)) {
-                    xxxxxxxxxxxx conflict xxxxxxxxxxx;
+            if (j == my_segment)
+                continue;
+            if (was_read_remote(get_segment_base(j), hashtableobj)) {
+                /* conflict! */
+                table->resize_counter = rc;    /* unlock */
+                if (write_read_contention_management(j, hashtableobj)) {
+                    /* If we reach this point, we didn't abort, but we
+                       had to wait for the other thread to commit.  If
+                       we did, then we have to restart. */
+                    return true;
+                    ...;
+                    
+                    }
+                    /* we aborted the other transaction without waiting, so
+                       we can just break out of this loop on
+                       modified_old_objects and continue with the next
+                       segment */
+                    
+                    xxx;
                 }
             }
         }
@@ -458,14 +487,15 @@
 static void _stm_compact_hashtable(stm_hashtable_t *hashtable)
 {
     stm_hashtable_table_t *table = hashtable->table;
-    assert(!IS_EVEN(table->resize_counter));
+    intptr_t rc = table->resize_counter;
+    assert(!IS_EVEN(rc));
 
     if ((hashtable->additions >> 8) * 4 > table->mask) {
         int segment_num = (hashtable->additions & 0xFF);
         if (!segment_num) segment_num = 1;
         hashtable->additions = segment_num;
         uintptr_t initial_rc = (table->mask + 1) * 4 + 1;
-        uintptr_t num_entries_times_6 = initial_rc - table->resize_counter;
+        uintptr_t num_entries_times_6 = initial_rc - (rc < 0 ? -rc : rc);
         uintptr_t count = INITIAL_HASHTABLE_SIZE;
         while (count * 4 < num_entries_times_6)
             count *= 2;
@@ -475,7 +505,7 @@
 
         dprintf(("compact with %ld items:\n", num_entries_times_6 / 6));
         _stm_rehash_hashtable(hashtable, count, /*remove_unread=*/segment_num,
-                              /*rc_must_be_negative=*/false);
+                              /*rc_must_be_negative=*/rc < 0);
     }
 
     table = hashtable->table;


More information about the pypy-commit mailing list