[pypy-commit] pypy stm-gc: Last missing piece in the C source: stm_copy_transactional_to_raw()
arigo
noreply at buildbot.pypy.org
Tue Feb 7 20:48:58 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52205:c1a57e0a3ac5
Date: 2012-02-07 20:48 +0100
http://bitbucket.org/pypy/pypy/changeset/c1a57e0a3ac5/
Log: Last missing piece in the C source: stm_copy_transactional_to_raw()
diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -288,18 +288,15 @@
# Initialize the copy by doing an stm raw copy of the bytes
stm_operations.stm_copy_transactional_to_raw(obj, localobj, size)
#
- # The raw copy done above includes all header fields.
- # Check at least the gc flags of the copy.
+ # The raw copy done above does not include the header fields.
hdr = self.header(obj)
localhdr = self.header(localobj)
GCFLAGS = (GCFLAG_GLOBAL | GCFLAG_WAS_COPIED)
ll_assert(hdr.tid & GCFLAGS == GCFLAGS,
"stm_write: bogus flags on source object")
- ll_assert(localhdr.tid & GCFLAGS == GCFLAGS,
- "stm_write: flags not copied!")
#
# Remove the GCFLAG_GLOBAL from the copy
- localhdr.tid &= ~GCFLAG_GLOBAL
+ localhdr.tid = hdr.tid & ~GCFLAG_GLOBAL
#
# Set the 'version' field of the local copy to be a pointer
# to the global obj. (The field is called 'version' because
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -106,10 +106,6 @@
locals()['stm_read_int%d' % _size] = _func
def stm_copy_transactional_to_raw(self, srcobj, dstobj, size):
- sizehdr = self._gc.gcheaderbuilder.size_gc_header
- srchdr = srcobj - sizehdr
- dsthdr = dstobj - sizehdr
- llmemory.raw_memcopy(srchdr, dsthdr, sizehdr)
llmemory.raw_memcopy(srcobj, dstobj, size)
self._transactional_copies.append((srcobj, dstobj))
diff --git a/pypy/translator/stm/src_stm/et.c b/pypy/translator/stm/src_stm/et.c
--- a/pypy/translator/stm/src_stm/et.c
+++ b/pypy/translator/stm/src_stm/et.c
@@ -430,6 +430,38 @@
}
/* lazy/lazy read instrumentation */
+#define STM_DO_READ(READ_OPERATION) \
+ retry: \
+ /* read the orec BEFORE we read anything else */ \
+ ovt = o->version; \
+ CFENCE; \
+ \
+ /* this tx doesn't hold any locks, so if the lock for this addr is \
+ held, there is contention. A lock is never hold for too long, \
+ so spinloop until it is released. */ \
+ if (IS_LOCKED_OR_NEWER(ovt, d->start_time)) \
+ { \
+ if (IS_LOCKED(ovt)) { \
+ tx_spinloop(7); \
+ goto retry; \
+ } \
+ /* else this location is too new, scale forward */ \
+ owner_version_t newts = get_global_timestamp(d) & ~1; \
+ validate_fast(d, 1); \
+ d->start_time = newts; \
+ } \
+ \
+ /* orec is unlocked, with ts <= start_time. read the location */ \
+ READ_OPERATION; \
+ \
+ /* postvalidate AFTER reading addr: */ \
+ CFENCE; \
+ if (__builtin_expect(o->version != ovt, 0)) \
+ goto retry; /* oups, try again */ \
+ \
+ oreclist_insert(&d->reads, (orec_t*)o);
+
+
#define STM_READ_WORD(SIZE, TYPE) \
TYPE stm_read_int##SIZE(void* addr, long offset) \
{ \
@@ -455,36 +487,7 @@
if (is_main_thread(d)) \
return *(TYPE *)(((char *)addr) + offset); \
\
- retry: \
- /* read the orec BEFORE we read anything else */ \
- ovt = o->version; \
- CFENCE; \
- \
- /* this tx doesn't hold any locks, so if the lock for this addr is \
- held, there is contention. A lock is never hold for too long, \
- so spinloop until it is released. */ \
- if (IS_LOCKED_OR_NEWER(ovt, d->start_time)) \
- { \
- if (IS_LOCKED(ovt)) { \
- tx_spinloop(7); \
- goto retry; \
- } \
- /* else this location is too new, scale forward */ \
- owner_version_t newts = get_global_timestamp(d) & ~1; \
- validate_fast(d, 1); \
- d->start_time = newts; \
- } \
- \
- /* orec is unlocked, with ts <= start_time. read the location */ \
- TYPE tmp = *(TYPE *)(((char *)addr) + offset); \
- \
- /* postvalidate AFTER reading addr: */ \
- CFENCE; \
- if (__builtin_expect(o->version != ovt, 0)) \
- goto retry; /* oups, try again */ \
- \
- oreclist_insert(&d->reads, (orec_t*)o); \
- \
+ STM_DO_READ(TYPE tmp = *(TYPE *)(((char *)addr) + offset)); \
return tmp; \
}
@@ -493,6 +496,22 @@
STM_READ_WORD(4, int)
STM_READ_WORD(8, long long)
+void stm_copy_transactional_to_raw(void *src, void *dst, long size)
+{
+ struct tx_descriptor *d = thread_descriptor;
+ volatile orec_t *o = get_orec(src);
+ owner_version_t ovt;
+
+ assert(!is_main_thread(d));
+
+ /* don't copy the header */
+ src = ((char *)src) + sizeof(orec_t);
+ dst = ((char *)dst) + sizeof(orec_t);
+ size -= sizeof(orec_t);
+
+ STM_DO_READ(memcpy(dst, src, size));
+}
+
static struct tx_descriptor *descriptor_init(_Bool is_main_thread)
{
diff --git a/pypy/translator/stm/test/test_stmgcintf.py b/pypy/translator/stm/test/test_stmgcintf.py
--- a/pypy/translator/stm/test/test_stmgcintf.py
+++ b/pypy/translator/stm/test/test_stmgcintf.py
@@ -144,7 +144,32 @@
def test_stm_size_getter(self):
def getsize(addr):
- xxx
+ dont_call_me
getter = llhelper(GETSIZE, getsize)
stm_operations.setup_size_getter(getter)
- # just tests that the function is really defined
+ # ^^^ just tests that the function is really defined
+
+ def test_stm_copy_transactional_to_raw(self):
+ # doesn't test STM behavior, but just that it appears to work
+ s1 = lltype.malloc(S1, flavor='raw')
+ s1.hdr.tid = stmgc.GCFLAG_GLOBAL
+ s1.hdr.version = llmemory.NULL
+ s1.x = 909
+ s1.y = 808
+ s2 = lltype.malloc(S1, flavor='raw')
+ s2.hdr.tid = -42 # non-initialized
+ s2.x = -42 # non-initialized
+ s2.y = -42 # non-initialized
+ #
+ s1_adr = llmemory.cast_ptr_to_adr(s1)
+ s2_adr = llmemory.cast_ptr_to_adr(s2)
+ size = llmemory.sizeof(S1)
+ stm_operations.stm_copy_transactional_to_raw(s1_adr, s2_adr, size)
+ #
+ assert s2.hdr.tid == -42 # not touched
+ assert s2.x == 909
+ assert s2.y == 808
+ #
+ lltype.free(s2, flavor='raw')
+ lltype.free(s1, flavor='raw')
+ test_stm_copy_transactional_to_raw.in_main_thread = False
More information about the pypy-commit
mailing list