Author: Armin Rigo <[email protected]>
Branch: c8-gil-like
Changeset: r1815:48f9b949581f
Date: 2015-06-12 13:39 +0200
http://bitbucket.org/pypy/stmgc/changeset/48f9b949581f/

Log:    Tentative fix: remove the two places setting 'TS_NONE' without the
        mutex_lock, which creates race conditions.

        Move the major collection at commit a bit earlier, at a point where
        the transaction being committed is still running like usual.

        Commit no longer does a safe_point at the end: if a safe point is
        requested, we now signal C_AT_SAFE_POINT but just leave.

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -324,10 +324,7 @@
     /* Don't check this 'cl'. This entry is already checked */
 
     if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
-        //assert(first_cl->next == INEV_RUNNING);
-        /* the above assert may fail when running a major collection
-           while the commit of the inevitable transaction is in progress
-           and the element is already attached */
+        assert(first_cl->next == INEV_RUNNING);
         return true;
     }
 
@@ -606,9 +603,6 @@
 
     if (is_commit) {
         /* compare with _validate_and_add_to_commit_log */
-        STM_PSEGMENT->transaction_state = TS_NONE;
-        STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
-
         list_clear(STM_PSEGMENT->modified_old_objects);
         STM_PSEGMENT->last_commit_log_entry = new;
         release_modification_lock_wr(STM_SEGMENT->segment_num);
@@ -640,16 +634,15 @@
                                       STM_PSEGMENT->modified_old_objects);
 
         /* compare with _validate_and_attach: */
-        STM_PSEGMENT->transaction_state = TS_NONE;
-        STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
+        acquire_modification_lock_wr(STM_SEGMENT->segment_num);
         list_clear(STM_PSEGMENT->modified_old_objects);
         STM_PSEGMENT->last_commit_log_entry = new;
 
-        usleep(100);  //XXX
-        
         /* do it: */
         bool yes = __sync_bool_compare_and_swap(&old->next, INEV_RUNNING, new);
         OPT_ASSERT(yes);
+
+        release_modification_lock_wr(STM_SEGMENT->segment_num);
     }
     else {
         _validate_and_attach(new, /*can_sleep=*/true);
@@ -1232,6 +1225,7 @@
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
 
+    assert(_has_mutex());
     STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
     STM_PSEGMENT->transaction_state = TS_NONE;
 
@@ -1242,6 +1236,13 @@
     if (tl != NULL)
         timing_event(tl, event);
 
+    /* If somebody is waiting for us to reach a safe point, we simply
+       signal it now and leave this transaction.  This should be enough
+       for synchronize_all_threads() to retry and notice that we are
+       no longer SP_RUNNING. */
+    if (STM_SEGMENT->nursery_end != NURSERY_END)
+        cond_signal(C_AT_SAFE_POINT);
+
     release_thread_segment(tl);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 }
@@ -1301,6 +1302,7 @@
 
     assert(!_has_mutex());
     assert(STM_PSEGMENT->safe_point == SP_RUNNING);
+    assert(STM_PSEGMENT->transaction_state != TS_NONE);
     if (globally_unique_transaction) {
         stm_fatalerror("cannot commit between stm_stop_all_other_threads "
                        "and stm_resume_all_other_threads");
@@ -1308,6 +1310,13 @@
 
     dprintf(("> stm_commit_transaction(external=%d)\n", (int)external));
     minor_collection(/*commit=*/ true, external);
+    if (!external && is_major_collection_requested()) {
+        s_mutex_lock();
+        if (is_major_collection_requested()) {   /* if still true */
+            major_collection_with_mutex();
+        }
+        s_mutex_unlock();
+    }
 
     push_large_overflow_objects_to_other_segments();
     /* push before validate. otherwise they are reachable too early */
@@ -1346,19 +1355,6 @@
 
     invoke_and_clear_user_callbacks(0);   /* for commit */
 
-    /* >>>>> there may be a FORK() happening in the safepoint below <<<<<*/
-    if (!external) {
-        enter_safe_point_if_requested();
-        assert(STM_SEGMENT->nursery_end == NURSERY_END);
-
-        /* if a major collection is required, do it here */
-        if (is_major_collection_requested()) {
-            major_collection_with_mutex();
-        }
-    }
-
-    
_verify_cards_cleared_in_all_lists(get_priv_segment(STM_SEGMENT->segment_num));
-
     /* done */
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
     assert(external == (tl == NULL));
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to