[pypy-commit] stmgc c7: fix race condition in abort

Raemi noreply at buildbot.pypy.org
Fri Jan 17 15:50:00 CET 2014


Author: Remi Meier <remi.meier at gmail.com>
Branch: c7
Changeset: r628:1030cba5f19d
Date: 2014-01-17 15:49 +0100
http://bitbucket.org/pypy/stmgc/changeset/1030cba5f19d/

Log:	fix race condition in abort

diff --git a/c7/core.c b/c7/core.c
--- a/c7/core.c
+++ b/c7/core.c
@@ -87,7 +87,7 @@
 static uintptr_t index_page_never_used;
 static struct stm_list_s *volatile pending_updates;
 static uint8_t flag_page_private[NB_PAGES];   /* xxx_PAGE constants above */
-
+static uint8_t write_locks[READMARKER_END - READMARKER_START];
 
 /************************************************************/
 uintptr_t _stm_reserve_page(void);
@@ -318,23 +318,23 @@
 
 static void push_modified_to_other_threads()
 {
+    /* WE HAVE THE EXCLUSIVE LOCK HERE */
+    
     struct stm_list_s *modified = _STM_TL2->modified_objects;
     char *local_base = _STM_TL2->thread_base;
     char *remote_base = get_thread_base(1 - _STM_TL2->thread_num);
     bool conflicted = 0;
-    char *t0_base = get_thread_base(0);
     
     STM_LIST_FOREACH(
         modified,
         ({
             if (!conflicted)
                 conflicted = _stm_was_read_remote(remote_base, item);
-            
+
             /* clear the write-lock */
-            struct object_s *t0_obj = (struct object_s*)
-                REAL_ADDRESS(t0_base, item);
-            assert(t0_obj->stm_write_lock);
-            t0_obj->stm_write_lock = 0;
+            uintptr_t lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START;
+            assert(write_locks[lock_idx]);
+            write_locks[lock_idx] = 0;
             
             char *src = REAL_ADDRESS(local_base, item);
             char *dst = REAL_ADDRESS(remote_base, item);
@@ -377,13 +377,10 @@
     /* privatize if SHARED_PAGE */
     _stm_privatize(pagenum);
 
-    /* lock the object for writing in thread 0's page */
-    uintptr_t t0_offset = (uintptr_t)obj;
-    char* t0_addr = get_thread_base(0) + t0_offset;
-    struct object_s *t0_obj = (struct object_s *)t0_addr;
-
-    int previous;
-    while ((previous = __sync_lock_test_and_set(&t0_obj->stm_write_lock, 1))) {
+    /* claim the write-lock for this object */
+    uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - READMARKER_START;
+    uint8_t previous;
+    while ((previous = __sync_lock_test_and_set(&write_locks[lock_idx], 1))) {
         stm_abort_transaction();
         /* XXX: only abort if we are younger */
         spin_loop();
@@ -710,6 +707,7 @@
 {
     munmap(object_pages, TOTAL_MEMORY);
     memset(flag_page_private, 0, sizeof(flag_page_private));
+    memset(write_locks, 0, sizeof(write_locks));
     pthread_rwlock_destroy(&rwlock_shared);
     object_pages = NULL;
 }
@@ -924,32 +922,30 @@
     struct stm_list_s *modified = _STM_TL2->modified_objects;
     char *local_base = _STM_TL2->thread_base;
     char *remote_base = get_thread_base(1 - _STM_TL2->thread_num);
-    char *t0_base = get_thread_base(0);
     
     STM_LIST_FOREACH(
         modified,
         ({
             /* note: same as push_modified_to... but src/dst swapped
                XXX: unify both... */
+            
             char *dst = REAL_ADDRESS(local_base, item);
             char *src = REAL_ADDRESS(remote_base, item);
             size_t size = stmcb_size((struct object_s*)src);
             memcpy(dst, src, size);
-            
+
             /* copying from the other thread re-added the
                WRITE_BARRIER flag */
             assert(item->stm_flags & GCFLAG_WRITE_BARRIER);
+
+            /* write all changes to the object before we release the
+               write lock below */
+            write_fence();
             
-            struct object_s *t0_obj = (struct object_s*)
-                REAL_ADDRESS(t0_base, item);
-            if (t0_base != local_base) {
-                /* clear the write-lock (WE have modified the obj) */
-                assert(t0_obj->stm_write_lock);
-                t0_obj->stm_write_lock = 0;
-            } else {
-                /* done by the memcpy */
-                assert(!t0_obj->stm_write_lock);
-            }
+            /* clear the write-lock */
+            uintptr_t lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START;
+            assert(write_locks[lock_idx]);
+            write_locks[lock_idx] = 0;
         }));
 }
 
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -335,6 +335,6 @@
             stm_start_safe_point()
         lib._stm_restore_local_state(thread_num)
         if lib._stm_is_in_transaction():
-            stm_stop_safe_point()
+            stm_stop_safe_point() # can raise Conflict
 
         


More information about the pypy-commit mailing list