[pypy-commit] stmgc c7-refactor: Fixes, and issues
arigo
noreply at buildbot.pypy.org
Fri Feb 14 22:07:41 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r739:8f59f0e3f05b
Date: 2014-02-14 22:07 +0100
http://bitbucket.org/pypy/stmgc/changeset/8f59f0e3f05b/
Log: Fixes, and issues
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -20,7 +20,7 @@
lock on the same object. */
/* By construction it should not be possible that the owner
- of the object is precisely us */
+ of the object is already us */
assert(current_lock_owner != STM_PSEGMENT->write_lock_num);
/* Who should abort here: this thread, or the other thread? */
@@ -31,6 +31,8 @@
if ((STM_PSEGMENT->approximate_start_time <
other_pseg->approximate_start_time) || is_inevitable()) {
/* we are the thread that must succeed */
+ XXX /* don't go here if the other thread is inevitable! */
+ ...
other_pseg->need_abort = 1;
_stm_start_safe_point(0);
/* XXX: not good, maybe should be signalled by other thread */
@@ -68,6 +70,10 @@
pages_privatize(((uintptr_t)obj) / 4096UL, 1);
}
+ /* do a read-barrier *before* the safepoints that may be issued in
+ contention_management() */
+ stm_read(obj);
+
/* claim the write-lock for this object */
do {
uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - READMARKER_START;
@@ -86,7 +92,6 @@
/* add the write-barrier-already-called flag ONLY if we succeeded in
getting the write-lock */
- stm_read(obj);
obj->stm_flags |= GCFLAG_WRITE_BARRIER_CALLED;
LIST_APPEND(STM_PSEGMENT->modified_objects, obj);
}
@@ -135,9 +140,53 @@
}
+static void push_modified_to_other_threads()
+{
+ long remote_num = 1 - STM_SEGMENT->segment_num;
+ char *local_base = STM_SEGMENT->segment_base;
+ char *remote_base = get_segment_base(remote_num);
+ bool conflicted = false;
+ uint8_t remote_version = get_segment(remote_num)->transaction_read_version;
+
+ LIST_FOREACH_R(
+ STM_PSEGMENT->modified_objects,
+ object_t * /*item*/,
+ ({
+ if (!conflicted)
+ conflicted = was_read_remote(remote_base, item,
+ remote_version);
+
+ /* clear the write-lock */
+ uintptr_t lock_idx = (((uintptr_t)item) >> 4) - READMARKER_START;
+ assert(write_locks[lock_idx] == _STM_TL->thread_num + 1);
+ write_locks[lock_idx] = 0;
+
+ _stm_move_object(item,
+ REAL_ADDRESS(local_base, item),
+ REAL_ADDRESS(remote_base, item));
+ }));
+
+ list_clear(STM_PSEGMENT->modified_objects);
+
+ if (conflicted) {
+ struct _thread_local1_s *remote_TL = (struct _thread_local1_s *)
+ REAL_ADDRESS(remote_base, _STM_TL);
+ remote_TL->need_abort = 1;
+ }
+}
+
void stm_commit_transaction(void)
{
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
+
+ /* cannot abort any more */
+ STM_SEGMENT->jmpbuf_ptr = NULL;
+
+ ...
+
+ /* copy modified object versions to other threads */
+ push_modified_to_other_threads();
+
release_thread_segment(tl);
reset_all_creation_markers();
}
@@ -146,6 +195,7 @@
{
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
stm_jmpbuf_t *jmpbuf_ptr = STM_SEGMENT->jmpbuf_ptr;
+ STM_SEGMENT->need_abort = 0;
release_thread_segment(tl);
reset_all_creation_markers();
diff --git a/c7/stm/misc.c b/c7/stm/misc.c
--- a/c7/stm/misc.c
+++ b/c7/stm/misc.c
@@ -46,3 +46,11 @@
return !!((((stm_creation_marker_t *)(((uintptr_t)obj) >> 8))->cm |
obj->stm_flags) & _STM_GCFLAG_WRITE_BARRIER_CALLED);
}
+
+static inline bool was_read_remote(char *base, object_t *obj,
+ uint8_t other_transaction_read_version)
+{
+ struct read_marker_s *marker = (struct read_marker_s *)
+ (base + (((uintptr_t)obj) >> 4));
+ return (marker->rm == other_transaction_read_version);
+}
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -71,11 +71,14 @@
We reset the markers 8 at a time, by writing null integers
until we reach a place that is already null.
*/
- LIST_FOREACH_R(STM_PSEGMENT->creation_markers, uintptr_t, ({
- uint64_t *p = (uint64_t *)(item & ~7);
- while (*p != 0)
- *p++ = 0;
- }));
+ LIST_FOREACH_R(
+ STM_PSEGMENT->creation_markers,
+ uintptr_t /*item*/,
+ ({
+ uint64_t *p = (uint64_t *)(item & ~7);
+ while (*p != 0)
+ *p++ = 0;
+ }));
list_clear(STM_PSEGMENT->creation_markers);
}
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -130,10 +130,12 @@
};
/* The read barrier must be called whenever the object 'obj' is read.
- It is not required to call it before reading: it can be called
- during or after too, as long as we are in the same transaction.
- If we might have finished the transaction and started the next
- one, then stm_read() needs to be called again.
+ It is not required to call it before reading: it can be delayed for a
+ bit, but we must still be in the same "scope": no allocation, no
+ transaction commit, nothing that can potentially collect or do a safe
+ point (like stm_write() on a different object). Also, if we might
+ have finished the transaction and started the next one, then
+ stm_read() needs to be called again.
*/
static inline void stm_read(object_t *obj)
{
@@ -150,7 +152,7 @@
static inline void stm_write(object_t *obj)
{
/* this is:
- 'if (ct == 0 && (stm_flags & WRITE_BARRIER_CALLED) == 0)'
+ 'if (cm == 0 && (stm_flags & WRITE_BARRIER_CALLED) == 0)'
assuming that 'cm' is either 0 (not created in current transaction)
or 0xff (created in current transaction) */
if (UNLIKELY(!((((stm_creation_marker_t *)(((uintptr_t)obj) >> 8))->cm |
More information about the pypy-commit
mailing list