Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r1882:c2e8b3841c76 Date: 2015-06-24 15:53 +0200 http://bitbucket.org/pypy/stmgc/changeset/c2e8b3841c76/
Log: Try to systematically emit "wait" events when we wait diff --git a/c8/stm/core.c b/c8/stm/core.c --- a/c8/stm/core.c +++ b/c8/stm/core.c @@ -511,10 +511,12 @@ try to detach an inevitable transaction regularly */ detached = fetch_detached_transaction(); if (detached == 0) { + EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE); if (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ, 0.00001)) goto wait_some_more; } } + EMIT_WAIT_DONE(); s_mutex_unlock(); if (detached != 0) @@ -1130,6 +1132,7 @@ static void _do_start_transaction(stm_thread_local_t *tl) { assert(!_stm_in_transaction(tl)); + tl->wait_event_emitted = 0; acquire_thread_segment(tl); /* GS invalid before this point! */ @@ -1318,6 +1321,7 @@ } assert(STM_SEGMENT->running_thread->self_or_0_if_atomic == (intptr_t)(STM_SEGMENT->running_thread)); + assert(STM_SEGMENT->running_thread->wait_event_emitted == 0); dprintf(("> stm_commit_transaction(external=%d)\n", (int)external)); minor_collection(/*commit=*/ true, external); @@ -1582,9 +1586,8 @@ if (any_soon_finished_or_inevitable_thread_segment() && num_waits <= NB_SEGMENTS) { -#if STM_TESTS - timing_become_inevitable(); /* for tests: another transaction */ - stm_abort_transaction(); /* is already inevitable, abort */ +#if STM_TESTS /* for tests: another transaction */ + stm_abort_transaction(); /* is already inevitable, abort */ #endif bool timed_out = false; @@ -1594,6 +1597,7 @@ !safe_point_requested()) { /* 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.000054321)) timed_out = true; @@ -1607,14 +1611,17 @@ not too common. We don't want two threads constantly detaching each other. */ intptr_t detached = fetch_detached_transaction(); - if (detached != 0) + if (detached != 0) { + EMIT_WAIT_DONE(); commit_fetched_detached_transaction(detached); + } } else { num_waits++; } goto retry_from_start; } + EMIT_WAIT_DONE(); if (!_validate_and_turn_inevitable()) goto retry_from_start; } diff --git a/c8/stm/marker.h b/c8/stm/marker.h --- a/c8/stm/marker.h +++ b/c8/stm/marker.h @@ -15,3 +15,28 @@ #define timing_become_inevitable() \ (timing_enabled() ? _timing_become_inevitable() : (void)0) + + +static inline void emit_wait(stm_thread_local_t *tl, enum stm_event_e event) +{ + if (!timing_enabled()) + return; + if (tl->wait_event_emitted != 0) { + if (tl->wait_event_emitted == event) + return; + stmcb_timing_event(tl, STM_WAIT_DONE, NULL); + } + tl->wait_event_emitted = event; + stmcb_timing_event(tl, event, NULL); +} + +static inline void emit_wait_done(stm_thread_local_t *tl) +{ + if (tl->wait_event_emitted != 0) { + tl->wait_event_emitted = 0; + stmcb_timing_event(tl, STM_WAIT_DONE, NULL); + } +} + +#define EMIT_WAIT(event) emit_wait(STM_SEGMENT->running_thread, event) +#define EMIT_WAIT_DONE() emit_wait_done(STM_SEGMENT->running_thread) diff --git a/c8/stm/sync.c b/c8/stm/sync.c --- a/c8/stm/sync.c +++ b/c8/stm/sync.c @@ -243,13 +243,13 @@ /* No segment available. Wait until release_thread_segment() signals that one segment has been freed. Note that we prefer waiting rather than detaching an inevitable transaction, here. */ - timing_event(tl, STM_WAIT_FREE_SEGMENT); + emit_wait(tl, STM_WAIT_FREE_SEGMENT); cond_wait(C_SEGMENT_FREE); - timing_event(tl, STM_WAIT_DONE); goto retry_from_start; got_num: + emit_wait_done(tl); OPT_ASSERT(num >= 0 && num < NB_SEGMENTS-1); sync_ctl.in_use1[num+1] = 1; assert(STM_SEGMENT->segment_num == num+1); @@ -425,15 +425,15 @@ #ifdef STM_TESTS abort_with_mutex(); #endif - timing_event(STM_SEGMENT->running_thread, STM_WAIT_SYNC_PAUSE); + EMIT_WAIT(STM_WAIT_SYNC_PAUSE); cond_signal(C_AT_SAFE_POINT); STM_PSEGMENT->safe_point = SP_WAIT_FOR_C_REQUEST_REMOVED; cond_wait(C_REQUEST_REMOVED); STM_PSEGMENT->safe_point = SP_RUNNING; - timing_event(STM_SEGMENT->running_thread, STM_WAIT_DONE); assert(!STM_SEGMENT->no_safe_point_here); dprintf(("left safe point\n")); } + EMIT_WAIT_DONE(); } static void synchronize_all_threads(enum sync_type_e sync_type) @@ -461,12 +461,14 @@ intptr_t detached = fetch_detached_transaction(); if (detached != 0) { + EMIT_WAIT_DONE(); remove_requests_for_safe_point(); /* => C_REQUEST_REMOVED */ s_mutex_unlock(); commit_fetched_detached_transaction(detached); s_mutex_lock(); goto restart; } + EMIT_WAIT(STM_WAIT_SYNCING); STM_PSEGMENT->safe_point = SP_WAIT_FOR_C_AT_SAFE_POINT; cond_wait_timeout(C_AT_SAFE_POINT, 0.00001); /* every 10 microsec, try again fetch_detached_transaction() */ @@ -477,6 +479,7 @@ abort_with_mutex(); } } + EMIT_WAIT_DONE(); if (UNLIKELY(sync_type == STOP_OTHERS_AND_BECOME_GLOBALLY_UNIQUE)) { globally_unique_transaction = true; diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -71,6 +71,7 @@ /* the next fields are handled internally by the library */ int last_associated_segment_num; /* always a valid seg num */ int thread_local_counter; + int wait_event_emitted; struct stm_thread_local_s *prev, *next; intptr_t self_or_0_if_atomic; void *creating_pthread[2]; @@ -580,10 +581,6 @@ STM_TRANSACTION_COMMIT, STM_TRANSACTION_ABORT, - /* write-read contention: a "marker" is included in the PYPYSTM file - saying where the write was done. Followed by STM_TRANSACTION_ABORT. */ - STM_CONTENTION_WRITE_READ, - /* inevitable contention: all threads that try to become inevitable have a STM_BECOME_INEVITABLE event with a position marker. Then, if it waits it gets a STM_WAIT_OTHER_INEVITABLE. It is possible @@ -591,8 +588,14 @@ STM_TRANSACTION_ABORT if it fails to become inevitable. */ STM_BECOME_INEVITABLE, - /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */ + /* write-read contention: a "marker" is included in the PYPYSTM file + saying where the write was done. Followed by STM_TRANSACTION_ABORT. */ + STM_CONTENTION_WRITE_READ, + + /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE or + possibly STM_TRANSACTION_ABORT */ STM_WAIT_FREE_SEGMENT, + STM_WAIT_SYNCING, STM_WAIT_SYNC_PAUSE, STM_WAIT_OTHER_INEVITABLE, STM_WAIT_DONE, diff --git a/c8/test/support.py b/c8/test/support.py --- a/c8/test/support.py +++ b/c8/test/support.py @@ -132,10 +132,6 @@ STM_TRANSACTION_COMMIT, STM_TRANSACTION_ABORT, - /* write-read contention: a "marker" is included in the PYPYSTM file - saying where the write was done. Followed by STM_TRANSACTION_ABORT. */ - STM_CONTENTION_WRITE_READ, - /* inevitable contention: all threads that try to become inevitable have a STM_BECOME_INEVITABLE event with a position marker. Then, if it waits it gets a STM_WAIT_OTHER_INEVITABLE. It is possible @@ -143,8 +139,14 @@ STM_TRANSACTION_ABORT if it fails to become inevitable. */ STM_BECOME_INEVITABLE, - /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */ + /* write-read contention: a "marker" is included in the PYPYSTM file + saying where the write was done. Followed by STM_TRANSACTION_ABORT. */ + STM_CONTENTION_WRITE_READ, + + /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE or + possibly STM_TRANSACTION_ABORT */ STM_WAIT_FREE_SEGMENT, + STM_WAIT_SYNCING, STM_WAIT_SYNC_PAUSE, STM_WAIT_OTHER_INEVITABLE, STM_WAIT_DONE, _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit