[pypy-commit] stmgc c7-refactor: Progress
arigo
noreply at buildbot.pypy.org
Sat Feb 15 23:42:09 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r743:8201455ea6be
Date: 2014-02-15 23:41 +0100
http://bitbucket.org/pypy/stmgc/changeset/8201455ea6be/
Log: Progress
diff --git a/c7/stm/contention.c b/c7/stm/contention.c
--- a/c7/stm/contention.c
+++ b/c7/stm/contention.c
@@ -3,7 +3,7 @@
#endif
-static void contention_management(uint8_t other_segment_num)
+static void contention_management(uint8_t other_segment_num, bool wait)
{
/* A simple contention manager. Called when we do stm_write()
on an object, but some other thread already holds the write
@@ -16,12 +16,6 @@
struct stm_priv_segment_info_s* other_pseg;
other_pseg = get_priv_segment(other_segment_num);
- /* note: other_pseg is currently running a transaction, and it cannot
- commit or abort unexpectedly, because to do that it would need to
- suspend us. So the reading of other_pseg->start_time and
- other_pseg->transaction_state is stable, with one exception: the
- 'transaction_state' can go from TS_REGULAR to TS_INEVITABLE under
- our feet. */
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
/* I'm inevitable, so the other is not. */
assert(other_pseg->transaction_state != TS_INEVITABLE);
@@ -42,7 +36,7 @@
abort. */
abort_with_mutex();
}
- else {
+ else if (wait) {
/* otherwise, we will issue a safe point and wait: */
STM_PSEGMENT->safe_point = SP_SAFE_POINT;
diff --git a/c7/stm/contention.h b/c7/stm/contention.h
--- a/c7/stm/contention.h
+++ b/c7/stm/contention.h
@@ -1,2 +1,2 @@
-static void contention_management(uint8_t other_segment_num);
+static void contention_management(uint8_t other_segment_num, bool wait);
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -7,8 +7,6 @@
static uint8_t write_locks[READMARKER_END - READMARKER_START];
-static void abort_with_mutex(void) __attribute__((noreturn));
-
static void teardown_core(void)
{
memset(write_locks, 0, sizeof(write_locks));
@@ -58,7 +56,7 @@
By construction it should not be possible that the owner
of the object is already us */
mutex_lock();
- contention_management(prev_owner - 1);
+ contention_management(prev_owner - 1, true);
mutex_unlock();
} while (1);
@@ -120,15 +118,31 @@
}
-static bool detect_write_read_conflicts(void)
+/************************************************************/
+
+#if NB_SEGMENTS != 2
+# error "The logic in the functions below only works with two segments"
+#endif
+
+static void wait_for_other_safe_points(void)
+{
+ long remote_num = 1 - STM_SEGMENT->segment_num;
+ while (get_priv_segment(remote_num)->safe_point == SP_RUNNING) {
+ cond_wait();
+ }
+}
+
+static void detect_write_read_conflicts(void)
{
long remote_num = 1 - STM_SEGMENT->segment_num;
char *remote_base = get_segment_base(remote_num);
uint8_t remote_version = get_segment(remote_num)->transaction_read_version;
-#if NB_SEGMENTS != 2
-# error "This logic only works with two segments"
-#endif
+ switch (get_priv_segment(remote_num)->transaction_state) {
+ case TS_NONE:
+ case TS_MUST_ABORT:
+ return; /* no need to do any check */
+ }
LIST_FOREACH_R(
STM_PSEGMENT->modified_objects,
@@ -136,11 +150,13 @@
({
if (was_read_remote(remote_base, item, remote_version)) {
/* A write-read conflict! */
- contention_management(remote_num);
- return true;
+ contention_management(remote_num, false);
+
+ /* If we reach this point, it means we aborted the other
+ thread. We're done here. */
+ return;
}
}));
- return false;
}
static void push_modified_to_other_segments(void)
@@ -148,17 +164,18 @@
long remote_num = 1 - STM_SEGMENT->segment_num;
char *local_base = STM_SEGMENT->segment_base;
char *remote_base = get_segment_base(remote_num);
-
-#if NB_SEGMENTS != 2
-# error "This logic only works with two segments"
-#endif
+ bool remote_active =
+ (get_priv_segment(remote_num)->transaction_state == TS_REGULAR ||
+ get_priv_segment(remote_num)->transaction_state == TS_INEVITABLE);
LIST_FOREACH_R(
STM_PSEGMENT->modified_objects,
object_t * /*item*/,
({
- assert(!was_read_remote(remote_base, item,
+ if (remote_active) {
+ assert(!was_read_remote(remote_base, item,
get_segment(remote_num)->transaction_read_version));
+ }
/* clear the write-lock */
uintptr_t lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START;
@@ -176,8 +193,6 @@
void stm_commit_transaction(void)
{
mutex_lock();
-
- restart:
assert(STM_PSEGMENT->safe_point = SP_RUNNING);
switch (STM_PSEGMENT->transaction_state) {
@@ -193,9 +208,11 @@
assert(!"commit: bad transaction_state");
}
+ /* wait until the other thread is at a safe-point */
+ wait_for_other_safe_points();
+
/* detect conflicts */
- if (detect_write_read_conflicts())
- goto restart;
+ detect_write_read_conflicts();
/* cannot abort any more from here */
assert(STM_PSEGMENT->transaction_state != TS_MUST_ABORT);
@@ -223,9 +240,6 @@
static void abort_with_mutex(void)
{
- stm_thread_local_t *tl = STM_SEGMENT->running_thread;
- stm_jmpbuf_t *jmpbuf_ptr = STM_SEGMENT->jmpbuf_ptr;
-
switch (STM_PSEGMENT->transaction_state) {
case TS_REGULAR:
case TS_MUST_ABORT:
@@ -236,6 +250,8 @@
assert(!"abort: bad transaction_state");
}
+ stm_jmpbuf_t *jmpbuf_ptr = STM_SEGMENT->jmpbuf_ptr;
+ stm_thread_local_t *tl = STM_SEGMENT->running_thread;
release_thread_segment(tl); /* includes the cond_broadcast(); */
STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
STM_PSEGMENT->transaction_state = TS_NONE;
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -109,3 +109,4 @@
}
static void teardown_core(void);
+static void abort_with_mutex(void) __attribute__((noreturn));
diff --git a/c7/stm/sync.c b/c7/stm/sync.c
--- a/c7/stm/sync.c
+++ b/c7/stm/sync.c
@@ -80,11 +80,19 @@
static inline void cond_wait(void)
{
+#ifdef STM_NO_COND_WAIT
+ fprintf(stderr, "*** cond_wait called!");
+ abort();
+#endif
+
if (UNLIKELY(pthread_cond_wait(&sync_ctl.global_cond,
&sync_ctl.global_mutex) != 0)) {
perror("pthread_cond_wait");
abort();
}
+
+ if (STM_PSEGMENT->transaction_state == TS_MUST_ABORT)
+ abort_with_mutex();
}
static inline void cond_broadcast(void)
@@ -166,12 +174,19 @@
assert(STM_SEGMENT->running_thread == tl);
}
-void _stm_start_safe_point(int flags)
+#if STM_TESTS
+void _stm_start_safe_point(void)
{
- //...
+ assert(STM_PSEGMENT->safe_point == SP_RUNNING);
+ STM_PSEGMENT->safe_point = SP_SAFE_POINT_CAN_COLLECT;
}
-void _stm_stop_safe_point(int flags)
+void _stm_stop_safe_point(void)
{
- //...
+ assert(STM_PSEGMENT->safe_point == SP_SAFE_POINT_CAN_COLLECT);
+ STM_PSEGMENT->safe_point = SP_RUNNING;
+
+ if (STM_PSEGMENT->transaction_state == TS_MUST_ABORT)
+ stm_abort_transaction();
}
+#endif
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -81,8 +81,6 @@
stm_char *_stm_allocate_slowpath(ssize_t);
void _stm_become_inevitable(char*);
void _stm_start_transaction(stm_thread_local_t *, stm_jmpbuf_t *);
-void _stm_start_safe_point(int flags);
-void _stm_stop_safe_point(int flags);
#ifdef STM_TESTS
bool _stm_was_read(object_t *obj);
@@ -94,6 +92,8 @@
void _stm_test_switch(stm_thread_local_t *tl);
object_t *_stm_allocate_old(ssize_t size_rounded_up);
void _stm_large_dump(void);
+void _stm_start_safe_point(void);
+void _stm_stop_safe_point(void);
#endif
#define _STM_GCFLAG_WRITE_BARRIER_CALLED 0x80
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -66,12 +66,8 @@
void _set_type_id(object_t *obj, uint32_t h);
uint32_t _get_type_id(object_t *obj);
-#define LOCK_COLLECT ...
-#define LOCK_EXCLUSIVE ...
-#define THREAD_YIELD ...
-
-void _stm_start_safe_point(int);
-bool _check_stop_safe_point(int);
+void _stm_start_safe_point(void);
+bool _check_stop_safe_point(void);
""")
@@ -138,12 +134,6 @@
typedef TLPREFIX struct myobj_s myobj_t;
#define SIZEOF_MYOBJ sizeof(struct myobj_s)
-enum {
- LOCK_COLLECT = 1,
- LOCK_EXCLUSIVE = 2,
- THREAD_YIELD = 4,
-};
-
uint8_t _stm_get_flags(object_t *obj) {
return obj->stm_flags;
@@ -195,13 +185,13 @@
}
#endif
-bool _check_stop_safe_point(int flags) {
+bool _check_stop_safe_point(void) {
stm_jmpbuf_t here;
stm_segment_info_t *segment = STM_SEGMENT;
if (__builtin_setjmp(here) == 0) { // returned directly
assert(segment->jmpbuf_ptr == (stm_jmpbuf_t *)-1);
segment->jmpbuf_ptr = &here;
- _stm_stop_safe_point(flags);
+ _stm_stop_safe_point();
segment->jmpbuf_ptr = (stm_jmpbuf_t *)-1;
return 0;
}
@@ -287,7 +277,7 @@
}
''', sources=source_files,
- define_macros=[('STM_TESTS', '1')],
+ define_macros=[('STM_TESTS', '1'), ('STM_NO_COND_WAIT', '1')],
undef_macros=['NDEBUG'],
include_dirs=[parent_dir],
extra_compile_args=['-g', '-O0', '-Werror'],
@@ -369,10 +359,10 @@
def stm_start_safe_point():
- lib._stm_start_safe_point(lib.LOCK_COLLECT)
+ lib._stm_start_safe_point()
def stm_stop_safe_point():
- if lib._check_stop_safe_point(lib.LOCK_COLLECT):
+ if lib._check_stop_safe_point():
raise Conflict()
def stm_become_inevitable():
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -96,7 +96,7 @@
self.commit_transaction()
#
py.test.raises(Conflict, self.switch, 0) # detects rw conflict
-
+
def test_commit_fresh_objects(self):
self.start_transaction()
lp = stm_allocate(16)
More information about the pypy-commit
mailing list