[pypy-commit] stmgc c7-refactor: Fixes, and issues

arigo noreply at buildbot.pypy.org
Fri Feb 14 22:07:41 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r739:8f59f0e3f05b
Date: 2014-02-14 22:07 +0100
http://bitbucket.org/pypy/stmgc/changeset/8f59f0e3f05b/

Log:	Fixes, and issues

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -20,7 +20,7 @@
        lock on the same object. */
 
     /* By construction it should not be possible that the owner
-       of the object is precisely us */
+       of the object is already us */
     assert(current_lock_owner != STM_PSEGMENT->write_lock_num);
 
     /* Who should abort here: this thread, or the other thread? */
@@ -31,6 +31,8 @@
     if ((STM_PSEGMENT->approximate_start_time <
             other_pseg->approximate_start_time) || is_inevitable()) {
         /* we are the thread that must succeed */
+        XXX  /* don't go here if the other thread is inevitable! */
+        ...                           
         other_pseg->need_abort = 1;
         _stm_start_safe_point(0);
         /* XXX: not good, maybe should be signalled by other thread */
@@ -68,6 +70,10 @@
         pages_privatize(((uintptr_t)obj) / 4096UL, 1);
     }
 
+    /* do a read-barrier *before* the safepoints that may be issued in
+       contention_management() */
+    stm_read(obj);
+
     /* claim the write-lock for this object */
     do {
         uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - READMARKER_START;
@@ -86,7 +92,6 @@
 
     /* add the write-barrier-already-called flag ONLY if we succeeded in
        getting the write-lock */
-    stm_read(obj);
     obj->stm_flags |= GCFLAG_WRITE_BARRIER_CALLED;
     LIST_APPEND(STM_PSEGMENT->modified_objects, obj);
 }
@@ -135,9 +140,53 @@
 }
 
 
+static void push_modified_to_other_threads()
+{
+    long remote_num = 1 - STM_SEGMENT->segment_num;
+    char *local_base = STM_SEGMENT->segment_base;
+    char *remote_base = get_segment_base(remote_num);
+    bool conflicted = false;
+    uint8_t remote_version = get_segment(remote_num)->transaction_read_version;
+
+    LIST_FOREACH_R(
+        STM_PSEGMENT->modified_objects,
+        object_t * /*item*/,
+        ({
+            if (!conflicted)
+                conflicted = was_read_remote(remote_base, item,
+                                             remote_version);
+
+            /* clear the write-lock */
+            uintptr_t lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START;
+            assert(write_locks[lock_idx] == _STM_TL->thread_num + 1);
+            write_locks[lock_idx] = 0;
+
+            _stm_move_object(item,
+                             REAL_ADDRESS(local_base, item),
+                             REAL_ADDRESS(remote_base, item));
+        }));
+
+    list_clear(STM_PSEGMENT->modified_objects);
+
+    if (conflicted) {
+        struct _thread_local1_s *remote_TL = (struct _thread_local1_s *)
+            REAL_ADDRESS(remote_base, _STM_TL);
+        remote_TL->need_abort = 1;
+    }
+}
+
 void stm_commit_transaction(void)
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
+
+    /* cannot abort any more */
+    STM_SEGMENT->jmpbuf_ptr = NULL;
+
+    ...
+
+    /* copy modified object versions to other threads */
+    push_modified_to_other_threads();
+
     release_thread_segment(tl);
     reset_all_creation_markers();
 }
@@ -146,6 +195,7 @@
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
     stm_jmpbuf_t *jmpbuf_ptr = STM_SEGMENT->jmpbuf_ptr;
+    STM_SEGMENT->need_abort = 0;
     release_thread_segment(tl);
     reset_all_creation_markers();
 
diff --git a/c7/stm/misc.c b/c7/stm/misc.c
--- a/c7/stm/misc.c
+++ b/c7/stm/misc.c
@@ -46,3 +46,11 @@
     return !!((((stm_creation_marker_t *)(((uintptr_t)obj) >> 8))->cm |
                obj->stm_flags) & _STM_GCFLAG_WRITE_BARRIER_CALLED);
 }
+
+static inline bool was_read_remote(char *base, object_t *obj,
+                                   uint8_t other_transaction_read_version)
+{
+    struct read_marker_s *marker = (struct read_marker_s *)
+        (base + (((uintptr_t)obj) >> 4));
+    return (marker->rm == other_transaction_read_version);
+}
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -71,11 +71,14 @@
        We reset the markers 8 at a time, by writing null integers
        until we reach a place that is already null.
     */
-    LIST_FOREACH_R(STM_PSEGMENT->creation_markers, uintptr_t, ({
-        uint64_t *p = (uint64_t *)(item & ~7);
-        while (*p != 0)
-            *p++ = 0;
-    }));
+    LIST_FOREACH_R(
+        STM_PSEGMENT->creation_markers,
+        uintptr_t /*item*/,
+        ({
+            uint64_t *p = (uint64_t *)(item & ~7);
+            while (*p != 0)
+                *p++ = 0;
+        }));
 
     list_clear(STM_PSEGMENT->creation_markers);
 }
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -130,10 +130,12 @@
 };
 
 /* The read barrier must be called whenever the object 'obj' is read.
-   It is not required to call it before reading: it can be called
-   during or after too, as long as we are in the same transaction.
-   If we might have finished the transaction and started the next
-   one, then stm_read() needs to be called again.
+   It is not required to call it before reading: it can be delayed for a
+   bit, but we must still be in the same "scope": no allocation, no
+   transaction commit, nothing that can potentially collect or do a safe
+   point (like stm_write() on a different object).  Also, if we might
+   have finished the transaction and started the next one, then
+   stm_read() needs to be called again.
 */
 static inline void stm_read(object_t *obj)
 {
@@ -150,7 +152,7 @@
 static inline void stm_write(object_t *obj)
 {
     /* this is:
-           'if (ct == 0 && (stm_flags & WRITE_BARRIER_CALLED) == 0)'
+           'if (cm == 0 && (stm_flags & WRITE_BARRIER_CALLED) == 0)'
          assuming that 'cm' is either 0 (not created in current transaction)
                                 or 0xff (created in current transaction) */
     if (UNLIKELY(!((((stm_creation_marker_t *)(((uintptr_t)obj) >> 8))->cm |


More information about the pypy-commit mailing list