Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit