[pypy-commit] stmgc default: (remi, arigo)

arigo noreply at buildbot.pypy.org
Mon Feb 23 16:26:55 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1645:61743f8ebe26
Date: 2015-02-23 16:27 +0100
http://bitbucket.org/pypy/stmgc/changeset/61743f8ebe26/

Log:	(remi, arigo)

	Maybe fix a bug, by making it explicit in each stm_thread_local if
	it is running or not (associated_segment_num >= 1 or == -1).

diff --git a/c7/stm/extra.c b/c7/stm/extra.c
--- a/c7/stm/extra.c
+++ b/c7/stm/extra.c
@@ -6,15 +6,21 @@
 static long register_callbacks(stm_thread_local_t *tl,
                                void *key, void callback(void *), long index)
 {
-    if (!(_stm_in_transaction(tl) && tl == STM_SEGMENT->running_thread)) {
-        /* check that the current thread-local is really running the
-           transaction in STM_SEGMENT, and do nothing otherwise. */
+    if (tl->associated_segment_num == -1) {
+        /* check that the provided thread-local is really running a
+           transaction, and do nothing otherwise. */
         return -1;
     }
-
+    /* The tl was only here to check that.  We're really using
+       STM_PSEGMENT below, which is often but not always the
+       segment corresponding to the tl.  One case where it's not
+       the case is if this gets called from stmcb_light_finalizer()
+       from abort_finalizers() from major collections or contention.
+    */
     if (STM_PSEGMENT->transaction_state != TS_REGULAR) {
         /* ignore callbacks if we're in an inevitable transaction
            (which cannot abort) */
+        assert(STM_PSEGMENT->transaction_state == TS_INEVITABLE);
         return -1;
     }
 
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -418,12 +418,12 @@
 
     stm_thread_local_t *tl = stm_all_thread_locals;
     do {
-        /* If 'tl' is currently running, its 'associated_segment_num'
+        /* If 'tl' is currently running, its 'last_associated_segment_num'
            field is the segment number that contains the correct
            version of its overflowed objects.  If not, then the
            field is still some correct segment number, and it doesn't
            matter which one we pick. */
-        char *segment_base = get_segment_base(tl->associated_segment_num);
+        char *segment_base = get_segment_base(tl->last_associated_segment_num);
 
         struct stm_shadowentry_s *current = tl->shadowstack;
         struct stm_shadowentry_s *base = tl->shadowstack_base;
diff --git a/c7/stm/marker.c b/c7/stm/marker.c
--- a/c7/stm/marker.c
+++ b/c7/stm/marker.c
@@ -58,6 +58,7 @@
     */
     long i;
     int in_segment_num = out_marker->tl->associated_segment_num;
+    assert(in_segment_num >= 1);
     struct stm_priv_segment_info_s *pseg = get_priv_segment(in_segment_num);
     struct list_s *mlst = pseg->modified_old_objects;
     struct list_s *mlstm = pseg->modified_old_objects_markers;
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -255,7 +255,7 @@
         tl->prev = stm_all_thread_locals->prev;
         stm_all_thread_locals->prev->next = tl;
         stm_all_thread_locals->prev = tl;
-        num = tl->prev->associated_segment_num;
+        num = tl->prev->last_associated_segment_num;
     }
     tl->thread_local_obj = NULL;
 
@@ -263,7 +263,8 @@
        assign the same number to all of them and they would get their own
        numbers automatically. */
     num = (num % NB_SEGMENTS) + 1;
-    tl->associated_segment_num = num;
+    tl->associated_segment_num = -1;
+    tl->last_associated_segment_num = num;
     tl->thread_local_counter = ++thread_local_counters;
     *_get_cpth(tl) = pthread_self();
     _init_shadow_stack(tl);
diff --git a/c7/stm/sync.c b/c7/stm/sync.c
--- a/c7/stm/sync.c
+++ b/c7/stm/sync.c
@@ -148,7 +148,7 @@
     assert(_has_mutex());
     assert(_is_tl_registered(tl));
 
-    int num = tl->associated_segment_num;
+    int num = tl->last_associated_segment_num;
     if (sync_ctl.in_use1[num - 1] == 0) {
         /* fast-path: we can get the same segment number than the one
            we had before.  The value stored in GS is still valid. */
@@ -167,8 +167,9 @@
         num = (num % NB_SEGMENTS) + 1;
         if (sync_ctl.in_use1[num - 1] == 0) {
             /* we're getting 'num', a different number. */
-            dprintf(("acquired different segment: %d->%d\n", tl->associated_segment_num, num));
-            tl->associated_segment_num = num;
+            dprintf(("acquired different segment: %d->%d\n",
+                     tl->last_associated_segment_num, num));
+            tl->last_associated_segment_num = num;
             set_gs_register(get_segment_base(num));
             goto got_num;
         }
@@ -186,6 +187,7 @@
     sync_ctl.in_use1[num - 1] = 1;
     assert(STM_SEGMENT->segment_num == num);
     assert(STM_SEGMENT->running_thread == NULL);
+    tl->associated_segment_num = tl->last_associated_segment_num;
     STM_SEGMENT->running_thread = tl;
     return true;
 }
@@ -204,10 +206,12 @@
     }
 
     assert(STM_SEGMENT->running_thread == tl);
+    assert(tl->associated_segment_num == tl->last_associated_segment_num);
+    tl->associated_segment_num = -1;
     STM_SEGMENT->running_thread = NULL;
 
-    assert(sync_ctl.in_use1[tl->associated_segment_num - 1] == 1);
-    sync_ctl.in_use1[tl->associated_segment_num - 1] = 0;
+    assert(sync_ctl.in_use1[tl->last_associated_segment_num - 1] == 1);
+    sync_ctl.in_use1[tl->last_associated_segment_num - 1] = 0;
 }
 
 __attribute__((unused))
@@ -218,9 +222,16 @@
 
 bool _stm_in_transaction(stm_thread_local_t *tl)
 {
-    int num = tl->associated_segment_num;
-    assert(1 <= num && num <= NB_SEGMENTS);
-    return get_segment(num)->running_thread == tl;
+    if (tl->associated_segment_num == -1) {
+        return false;
+    }
+    else {
+        int num = tl->associated_segment_num;
+        OPT_ASSERT(1 <= num && num <= NB_SEGMENTS);
+        OPT_ASSERT(num == tl->last_associated_segment_num);
+        OPT_ASSERT(get_segment(num)->running_thread == tl);
+        return true;
+    }
 }
 
 void _stm_test_switch(stm_thread_local_t *tl)
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -69,6 +69,7 @@
     long last_abort__bytes_in_nursery;
     /* the next fields are handled internally by the library */
     int associated_segment_num;
+    int last_associated_segment_num;
     int thread_local_counter;
     struct stm_thread_local_s *prev, *next;
     void *creating_pthread[2];


More information about the pypy-commit mailing list