Author: Tobias Weber <[email protected]>
Branch: c8-adaptive-trx-length-per-thread
Changeset: r2100:66f838f8595b
Date: 2017-07-11 13:15 +0200
http://bitbucket.org/pypy/stmgc/changeset/66f838f8595b/
Log: Merge starvation fix
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -1638,7 +1638,7 @@
void _stm_become_inevitable(const char *msg)
{
- int num_waits = 0;
+ int num_waits = 1;
timing_become_inevitable();
@@ -1649,42 +1649,42 @@
if (msg != MSG_INEV_DONT_SLEEP) {
dprintf(("become_inevitable: %s\n", msg));
- if (any_soon_finished_or_inevitable_thread_segment() &&
- num_waits <= NB_SEGMENTS) {
+ if (any_soon_finished_or_inevitable_thread_segment()) {
#if STM_TESTS /* for tests: another transaction */
stm_abort_transaction(); /* is already inevitable, abort */
#endif
+ signal_commit_to_inevitable_transaction();
+
s_mutex_lock();
if (any_soon_finished_or_inevitable_thread_segment() &&
- !safe_point_requested()) {
-
- signal_commit_to_inevitable_transaction();
+ !safe_point_requested() &&
+ num_waits <= NB_SEGMENTS) {
/* wait until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled */
EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
- if (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ,
0.00001)) {
- s_mutex_unlock();
- /* try to detach another inevitable transaction, but
- only after waiting a bit. This is necessary to avoid
- deadlocks in some situations, which are hopefully
- not too common. We don't want two threads constantly
- detaching each other. */
- intptr_t detached = fetch_detached_transaction();
- if (detached != 0) {
- EMIT_WAIT_DONE();
- commit_fetched_detached_transaction(detached);
- }
- goto retry_from_start;
+ if (cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ,
0.00001)) {
+ num_waits++;
}
- num_waits++;
}
s_mutex_unlock();
+ /* XXX try to detach another inevitable transaction, but
+ only after waiting a bit. This is necessary to avoid
+ deadlocks in some situations, which are hopefully
+ not too common. We don't want two threads constantly
+ detaching each other. */
+ intptr_t detached = fetch_detached_transaction();
+ if (detached != 0) {
+ EMIT_WAIT_DONE();
+ commit_fetched_detached_transaction(detached);
+ EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
+ }
goto retry_from_start;
}
else {
EMIT_WAIT_DONE();
if (!_validate_and_turn_inevitable()) {
+ EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
goto retry_from_start;
}
}
diff --git a/c8/stm/detach.c b/c8/stm/detach.c
--- a/c8/stm/detach.c
+++ b/c8/stm/detach.c
@@ -229,14 +229,18 @@
return STM_PSEGMENT->atomic_nesting_levels;
}
+// max intptr_t value is 7FFFFFFFFFFFFFFF on 64-bit => larger than 2 * huge
value
#define HUGE_INTPTR_VALUE 0x3000000000000000L
void stm_enable_atomic(stm_thread_local_t *tl)
{
if (!stm_is_atomic(tl)) {
+ // do for outermost atomic block only
tl->self_or_0_if_atomic = 0;
/* increment 'nursery_mark' by HUGE_INTPTR_VALUE, so that
- stm_should_break_transaction() returns always false */
+ stm_should_break_transaction() returns always false.
+ preserves the previous nursery_mark, unless it is < 0
+ or >= huge value */
intptr_t mark = (intptr_t)STM_SEGMENT->nursery_mark;
if (mark < 0)
mark = 0;
@@ -256,6 +260,7 @@
STM_PSEGMENT->atomic_nesting_levels--;
if (STM_PSEGMENT->atomic_nesting_levels == 0) {
+ // revert changes by stm_enable_atomic only if we left the outermost
atomic block
tl->self_or_0_if_atomic = (intptr_t)tl;
/* decrement 'nursery_mark' by HUGE_INTPTR_VALUE, to cancel
what was done in stm_enable_atomic() */
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -543,7 +543,7 @@
pseg->pub.nursery_mark -= nursery_used;
if (pseg->commit_if_not_atomic
- // && pseg->transaction_state == TS_INEVITABLE // TODO why does this
break the mechanism?
+ // && pseg->transaction_state == TS_INEVITABLE // TODO why does this
break the mechanism?
&& pseg->pub.running_thread->self_or_0_if_atomic != 0) {
// transaction is inevitable, not atomic, and commit has been
signalled by waiting thread: commit immediately
pseg->pub.nursery_mark = 0;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit