[pypy-commit] pypy stmgc-c8: import stmgc branch 'queue'
arigo
noreply at buildbot.pypy.org
Thu Jun 18 18:56:15 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c8
Changeset: r78188:c12cb756db2e
Date: 2015-06-18 17:52 +0100
http://bitbucket.org/pypy/pypy/changeset/c12cb756db2e/
Log: import stmgc branch 'queue'
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 @@
-d083e426a17d
+0a10e04f2119
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
@@ -495,6 +495,32 @@
static void readd_wb_executed_flags(void);
static void check_all_write_barrier_flags(char *segbase, struct list_s *list);
+static void wait_for_inevitable(void)
+{
+ intptr_t detached = 0;
+
+ s_mutex_lock();
+ wait_some_more:
+ if (safe_point_requested()) {
+ /* XXXXXX if the safe point below aborts, in
+ _validate_and_attach(), 'new' leaks */
+ enter_safe_point_if_requested();
+ }
+ else if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
+ /* loop until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled, but
+ try to detach an inevitable transaction regularly */
+ detached = fetch_detached_transaction();
+ if (detached == 0) {
+ if (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ, 0.00001))
+ goto wait_some_more;
+ }
+ }
+ s_mutex_unlock();
+
+ if (detached != 0)
+ commit_fetched_detached_transaction(detached);
+}
+
/* This is called to do stm_validate() and then attach 'new' at the
head of the 'commit_log_root' chained list. This function sleeps
and retries until it succeeds or aborts.
@@ -523,24 +549,10 @@
#endif
if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
- s_mutex_lock();
- if (safe_point_requested()) {
- /* XXXXXX if the safe point below aborts, 'new' leaks */
- enter_safe_point_if_requested();
- }
- else if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
- cond_wait(C_SEGMENT_FREE_OR_SAFE_POINT);
- }
- s_mutex_unlock();
+ wait_for_inevitable();
goto retry_from_start; /* redo _stm_validate() now */
}
- intptr_t detached = fetch_detached_transaction();
- if (detached != 0) {
- commit_fetched_detached_transaction(detached);
- goto retry_from_start;
- }
-
/* we must not remove the WB_EXECUTED flags before validation as
it is part of a condition in import_objects() called by
copy_bk_objs_in_page_from to not overwrite our modifications.
@@ -1119,7 +1131,7 @@
{
assert(!_stm_in_transaction(tl));
- while (!acquire_thread_segment(tl)) {}
+ acquire_thread_segment(tl);
/* GS invalid before this point! */
assert(STM_PSEGMENT->safe_point == SP_NO_TRANSACTION);
@@ -1571,13 +1583,33 @@
timing_become_inevitable(); /* for tests: another transaction */
stm_abort_transaction(); /* is already inevitable, abort */
#endif
+
+ bool timed_out = false;
+
s_mutex_lock();
if (any_soon_finished_or_inevitable_thread_segment() &&
!safe_point_requested()) {
- cond_wait(C_SEGMENT_FREE_OR_SAFE_POINT);
+
+ /* wait until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled */
+ if (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ,
+ 0.000054321))
+ timed_out = true;
}
s_mutex_unlock();
- num_waits++;
+
+ if (timed_out) {
+ /* 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)
+ commit_fetched_detached_transaction(detached);
+ }
+ else {
+ num_waits++;
+ }
goto retry_from_start;
}
if (!_validate_and_turn_inevitable())
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
@@ -203,10 +203,11 @@
#endif
-static bool acquire_thread_segment(stm_thread_local_t *tl)
+static void acquire_thread_segment(stm_thread_local_t *tl)
{
/* This function acquires a segment for the currently running thread,
and set up the GS register if it changed. */
+ retry_from_start:
assert(_has_mutex());
assert(_is_tl_registered(tl));
@@ -240,13 +241,13 @@
}
}
/* No segment available. Wait until release_thread_segment()
- signals that one segment has been freed. */
+ 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);
cond_wait(C_SEGMENT_FREE);
timing_event(tl, STM_WAIT_DONE);
- /* Return false to the caller, which will call us again */
- return false;
+ goto retry_from_start;
got_num:
OPT_ASSERT(num >= 0 && num < NB_SEGMENTS-1);
@@ -257,7 +258,6 @@
assert(!in_transaction(tl));
STM_SEGMENT->running_thread = tl;
assert(in_transaction(tl));
- return true;
}
static void release_thread_segment(stm_thread_local_t *tl)
@@ -266,7 +266,7 @@
assert(_has_mutex());
cond_signal(C_SEGMENT_FREE);
- cond_broadcast(C_SEGMENT_FREE_OR_SAFE_POINT); /* often no listener */
+ cond_broadcast(C_SEGMENT_FREE_OR_SAFE_POINT_REQ); /* often no listener */
assert(STM_SEGMENT->running_thread == tl);
segnum = STM_SEGMENT->segment_num;
@@ -362,7 +362,7 @@
assert(!pause_signalled);
pause_signalled = true;
dprintf(("request to pause\n"));
- cond_broadcast(C_SEGMENT_FREE_OR_SAFE_POINT);
+ cond_broadcast(C_SEGMENT_FREE_OR_SAFE_POINT_REQ);
}
static inline long count_other_threads_sp_running(void)
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
@@ -5,7 +5,7 @@
C_AT_SAFE_POINT,
C_REQUEST_REMOVED,
C_SEGMENT_FREE,
- C_SEGMENT_FREE_OR_SAFE_POINT,
+ C_SEGMENT_FREE_OR_SAFE_POINT_REQ,
C_QUEUE_OLD_ENTRIES,
C_QUEUE_FINISHED_MORE_TASKS,
_C_TOTAL
@@ -25,7 +25,7 @@
/* acquire and release one of the segments for running the given thread
(must have the mutex acquired!) */
-static bool acquire_thread_segment(stm_thread_local_t *tl);
+static void acquire_thread_segment(stm_thread_local_t *tl);
static void release_thread_segment(stm_thread_local_t *tl);
static void soon_finished_or_inevitable_thread_segment(void);
static bool any_soon_finished_or_inevitable_thread_segment(void);
More information about the pypy-commit
mailing list