Author: Tobias Weber <tobias_webe...@gmx.de> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit