Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r75861:4d74bdc4535a
Date: 2015-02-13 18:43 +0100
http://bitbucket.org/pypy/pypy/changeset/4d74bdc4535a/

Log:    Use stm_commit_and_start_inevitable() after starting a globally
        unique transaction.

diff --git a/rpython/jit/metainterp/compile.py 
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -248,16 +248,12 @@
     for box in loop.inputargs:
         assert isinstance(box, Box)
 
-    if rgc.stm_is_enabled():
-        rstm.stop_all_other_threads()
     target_token = loop.operations[-1].getdescr()
     resumekey.compile_and_attach(metainterp, loop)
 
     target_token = label.getdescr()
     assert isinstance(target_token, TargetToken)
     record_loop_or_bridge(metainterp_sd, loop)
-    if rgc.stm_is_enabled():
-        rstm.partial_commit_and_resume_other_threads()
 
     return target_token
 
@@ -824,13 +820,9 @@
     if new_trace.operations[-1].getopnum() != rop.LABEL:
         # We managed to create a bridge.  Dispatch to resumekey to
         # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr)
-        if rgc.stm_is_enabled():
-            rstm.stop_all_other_threads()
         target_token = new_trace.operations[-1].getdescr()
         resumekey.compile_and_attach(metainterp, new_trace)
         record_loop_or_bridge(metainterp_sd, new_trace)
-        if rgc.stm_is_enabled():
-            rstm.partial_commit_and_resume_other_threads()
         return target_token
     else:
         metainterp.retrace_needed(new_trace)
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -73,8 +73,9 @@
 def stop_all_other_threads():
     llop.stm_become_globally_unique_transaction(lltype.Void)
 
+@dont_look_inside
 def partial_commit_and_resume_other_threads():
-    hint_commit_soon()    # for now
+    llop.stm_commit_and_start_inevitable(lltype.Void)
 
 @specialize.arg(0)
 def should_break_transaction(keep):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -429,6 +429,7 @@
     'stm_get_root_stack_top': LLOp(sideeffects=False),
     'stm_become_inevitable':  LLOp(canmallocgc=True),
     'stm_become_globally_unique_transaction': LLOp(canmallocgc=True),
+    'stm_commit_and_start_inevitable': LLOp(canmallocgc=True),
     'stm_push_root':          LLOp(),
     'stm_pop_root_into':      LLOp(),
     'stm_commit_if_not_atomic':           LLOp(canmallocgc=True),
diff --git a/rpython/translator/stm/funcgen.py 
b/rpython/translator/stm/funcgen.py
--- a/rpython/translator/stm/funcgen.py
+++ b/rpython/translator/stm/funcgen.py
@@ -171,6 +171,9 @@
 def stm_become_globally_unique_transaction(funcgen, op):
     return 'pypy_stm_become_globally_unique_transaction();'
 
+def stm_commit_and_start_inevitable(funcgen, op):
+    return 'pypy_stm_commit_and_start_inevitable();'
+
 def stm_push_root(funcgen, op):
     arg0 = funcgen.expr(op.args[0])
     return 'STM_PUSH_ROOT(stm_thread_local, %s);' % (arg0,)
diff --git a/rpython/translator/stm/src_stm/revision 
b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-19bb1dde7aca
+756a54dd920b
diff --git a/rpython/translator/stm/src_stm/stm/core.c 
b/rpython/translator/stm/src_stm/stm/core.c
--- a/rpython/translator/stm/src_stm/stm/core.c
+++ b/rpython/translator/stm/src_stm/stm/core.c
@@ -331,10 +331,11 @@
 
 static void _stm_start_transaction(stm_thread_local_t *tl)
 {
-    assert(!_stm_in_transaction(tl));
-
-    while (!acquire_thread_segment(tl))
-        ;
+    if (!will_start_inevitable) {
+        assert(!_stm_in_transaction(tl));
+        while (!acquire_thread_segment(tl))
+            ;
+    }
     /* GS invalid before this point! */
 
     assert(STM_PSEGMENT->safe_point == SP_NO_TRANSACTION);
@@ -351,10 +352,12 @@
     STM_PSEGMENT->shadowstack_at_start_of_transaction = tl->shadowstack;
     STM_PSEGMENT->threadlocal_at_start_of_transaction = tl->thread_local_obj;
 
-    enter_safe_point_if_requested();
-    dprintf(("start_transaction\n"));
+    if (!will_start_inevitable) {
+        enter_safe_point_if_requested();
+        dprintf(("start_transaction\n"));
 
-    s_mutex_unlock();
+        s_mutex_unlock();
+    }
 
     /* Now running the SP_RUNNING start.  We can set our
        'transaction_read_version' after releasing the mutex,
@@ -828,7 +831,8 @@
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
     timing_event(tl, event);
 
-    release_thread_segment(tl);
+    if (!will_start_inevitable)
+        release_thread_segment(tl);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 }
 
@@ -848,6 +852,11 @@
 
     s_mutex_lock();
 
+    if (will_start_inevitable) {
+        assert(will_start_inevitable == 1);
+        assert(will_start_inevitable = 2);   /* 1 -> 2, only if !NDEBUG */
+    }
+
  restart:
     /* force all other threads to be paused.  They will unpause
        automatically when we are done here, i.e. at mutex_unlock().
@@ -906,6 +915,9 @@
     _finish_transaction(STM_TRANSACTION_COMMIT);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
+    if (will_start_inevitable)
+        return;    /* hack: return with the mutex still held */
+
     s_mutex_unlock();
 
     invoke_general_finalizers(tl);
@@ -1161,3 +1173,29 @@
     synchronize_all_threads(STOP_OTHERS_AND_BECOME_GLOBALLY_UNIQUE);
     s_mutex_unlock();
 }
+
+void stm_commit_and_start_inevitable(stm_thread_local_t *tl, const char *msg)
+{
+    stm_become_inevitable(tl, msg);   /* may still abort */
+
+    /* cannot abort any more from here */
+    will_start_inevitable = 1;
+
+    /* as long as 'will_start_inevitable' is true, we cannot release the
+       mutex_lock or do a cond_wait.  We must go through uninterrupted
+       with all the steps below.
+    */
+    stm_commit_transaction();
+    assert(will_start_inevitable == 2);
+    assert(_has_mutex());
+
+    _stm_start_transaction(tl);
+    assert(_has_mutex());
+
+    /* this line should be the only step from _stm_become_inevitable() we
+       must do in this case */
+    STM_PSEGMENT->transaction_state = TS_INEVITABLE;
+
+    will_start_inevitable = 0;
+    s_mutex_unlock();
+}
diff --git a/rpython/translator/stm/src_stm/stm/sync.c 
b/rpython/translator/stm/src_stm/stm/sync.c
--- a/rpython/translator/stm/src_stm/stm/sync.c
+++ b/rpython/translator/stm/src_stm/stm/sync.c
@@ -92,6 +92,7 @@
 static inline void s_mutex_unlock(void)
 {
     assert(_has_mutex_here);
+    assert(!will_start_inevitable);
     if (UNLIKELY(pthread_mutex_unlock(&sync_ctl.global_mutex) != 0))
         stm_fatalerror("pthread_mutex_unlock: %m");
     assert((_has_mutex_here = false, 1));
@@ -104,6 +105,7 @@
 #endif
 
     assert(_has_mutex_here);
+    assert(will_start_inevitable < 2);
     if (UNLIKELY(pthread_cond_wait(&sync_ctl.cond[ctype],
                                    &sync_ctl.global_mutex) != 0))
         stm_fatalerror("pthread_cond_wait/%d: %m", (int)ctype);
diff --git a/rpython/translator/stm/src_stm/stm/sync.h 
b/rpython/translator/stm/src_stm/stm/sync.h
--- a/rpython/translator/stm/src_stm/stm/sync.h
+++ b/rpython/translator/stm/src_stm/stm/sync.h
@@ -39,5 +39,6 @@
 static void committed_globally_unique_transaction(void);
 
 static bool pause_signalled, globally_unique_transaction;
+static uint8_t will_start_inevitable;
 
 void signal_other_to_commit_soon(struct stm_priv_segment_info_s *other_pseg);
diff --git a/rpython/translator/stm/src_stm/stmgc.h 
b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -409,6 +409,15 @@
 void stm_become_globally_unique_transaction(stm_thread_local_t *tl,
                                             const char *msg);
 
+/* Commit and start the next transaction as inevitable.  Provided the
+   commit succeeds, the next transaction is immediately made
+   inevitable: no other transaction can commit (or turn inevitable)
+   between the two steps.  The only reason to use this function
+   instead of stm_become_inevitable() is that the forced commit ends a
+   globally unique transaction.  If there is already another inevitable
+   transaction, this function will come stm_become_inevitable() first. */
+void stm_commit_and_start_inevitable(stm_thread_local_t *tl, const char *msg);
+
 
 /* Profiling events.  In the comments: content of the markers, if any */
 enum stm_event_e {
diff --git a/rpython/translator/stm/src_stm/stmgcintf.c 
b/rpython/translator/stm/src_stm/stmgcintf.c
--- a/rpython/translator/stm/src_stm/stmgcintf.c
+++ b/rpython/translator/stm/src_stm/stmgcintf.c
@@ -222,6 +222,11 @@
     stm_become_globally_unique_transaction(&stm_thread_local, "for the JIT");
 }
 
+void pypy_stm_commit_and_start_inevitable(void)
+{
+    stm_commit_and_start_inevitable(&stm_thread_local, "for the JIT");
+}
+
 long _pypy_stm_count(void)
 {
     static long value = 1;
diff --git a/rpython/translator/stm/src_stm/stmgcintf.h 
b/rpython/translator/stm/src_stm/stmgcintf.h
--- a/rpython/translator/stm/src_stm/stmgcintf.h
+++ b/rpython/translator/stm/src_stm/stmgcintf.h
@@ -30,6 +30,7 @@
 
 void _pypy_stm_become_inevitable(const char *);
 void pypy_stm_become_globally_unique_transaction(void);
+void pypy_stm_commit_and_start_inevitable(void);
 
 char *_pypy_stm_test_expand_marker(void);
 void pypy_stm_setup_expand_marker(long co_filename_ofs,
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to