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