[pypy-commit] pypy stm-gc: Fix and test stm_read_word(). Separate getsize_fn from stm_set_tls().
arigo
noreply at buildbot.pypy.org
Sat Feb 4 21:51:59 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52103:0f73f6e99efd
Date: 2012-02-04 21:51 +0100
http://bitbucket.org/pypy/pypy/changeset/0f73f6e99efd/
Log: Fix and test stm_read_word(). Separate getsize_fn from
stm_set_tls().
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
@@ -67,10 +67,9 @@
self.collector = Collector(self)
self.max_nursery_size = max_nursery_size
#
- def _do_get_size(obj): # indirection to hide 'self'
+ def _get_size(obj): # indirection to hide 'self'
return self.get_size(obj)
- GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],lltype.Signed))
- self._do_get_size = llhelper(GETSIZE, _do_get_size)
+ self._getsize_fn = _get_size
#
self.declare_readers()
self.declare_write_barrier()
@@ -78,6 +77,9 @@
def setup(self):
"""Called at run-time to initialize the GC."""
GCBase.setup(self)
+ GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],lltype.Signed))
+ self.stm_operations.setup_size_getter(
+ llhelper(GETSIZE, self._getsize_fn))
self.main_thread_tls = self.setup_thread(True)
self.mutex_lock = ll_thread.allocate_ll_lock()
@@ -95,7 +97,7 @@
Must be called only once per OS-level thread."""
tls = lltype.malloc(self.GCTLS, flavor='raw')
self.stm_operations.set_tls(llmemory.cast_ptr_to_adr(tls),
- self._do_get_size)
+ int(in_main_thread))
tls.nursery_start = self._alloc_nursery()
tls.nursery_size = self.max_nursery_size
tls.nursery_free = tls.nursery_start
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
@@ -22,17 +22,21 @@
threadnum = 0 # 0 = main thread; 1,2,3... = transactional threads
- def set_tls(self, tls, getsize_fn):
+ def setup_size_getter(self, getsize_fn):
+ self._getsize_fn = getsize_fn
+
+ def set_tls(self, tls, in_main_thread):
assert lltype.typeOf(tls) == llmemory.Address
assert tls
if self.threadnum == 0:
+ assert in_main_thread == 1
assert not hasattr(self, '_tls_dict')
self._tls_dict = {0: tls}
self._tldicts = {0: {}}
self._tldicts_iterators = {}
- self._getsize_fn = getsize_fn
self._transactional_copies = []
else:
+ assert in_main_thread == 0
self._tls_dict[self.threadnum] = tls
self._tldicts[self.threadnum] = {}
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
@@ -25,6 +25,8 @@
#ifdef PYPY_STANDALONE /* obscure: cannot include debug_print.h if compiled */
# define RPY_STM_DEBUG_PRINT /* via ll2ctypes; only include it in normal builds */
# include "src/debug_print.h"
+#else
+# define RPY_STM_ASSERT 1
#endif
/************************************************************/
@@ -62,17 +64,16 @@
struct tx_descriptor {
void *rpython_tls_object;
- long (*rpython_get_size)(void*);
jmp_buf *setjmp_buf;
owner_version_t start_time;
owner_version_t end_time;
/*unsigned long last_known_global_timestamp;*/
+ owner_version_t my_lock_word;
struct OrecList reads;
unsigned num_commits;
unsigned num_aborts[ABORT_REASONS];
unsigned num_spinloops[SPINLOOP_REASONS];
/*unsigned int spinloop_counter;*/
- owner_version_t my_lock_word;
struct RedoLog redolog; /* last item, because it's the biggest one */
};
@@ -80,6 +81,7 @@
if there is an inevitable transaction running */
static volatile unsigned long global_timestamp = 2;
static __thread struct tx_descriptor *thread_descriptor = NULL;
+static long (*rpython_get_size)(void*);
/************************************************************/
@@ -130,6 +132,11 @@
#endif
}
+static _Bool is_main_thread(struct tx_descriptor *d)
+{
+ return d->my_lock_word == 0;
+}
+
static _Bool is_inevitable(struct tx_descriptor *d)
{
return d->setjmp_buf == NULL;
@@ -147,7 +154,7 @@
void *globalobj = item->addr;
void *localobj = item->val;
owner_version_t p = item->p;
- long size = d->rpython_get_size(localobj);
+ long size = rpython_get_size(localobj);
memcpy(((char *)globalobj) + sizeof(orec_t),
((char *)localobj) + sizeof(orec_t),
size - sizeof(orec_t));
@@ -339,20 +346,26 @@
static void mutex_lock(void)
{
unsigned long pself = (unsigned long)pthread_self();
+#ifdef RPY_STM_DEBUG_PRINT
if (PYPY_HAVE_DEBUG_PRINTS) fprintf(PYPY_DEBUG_FILE,
"%lx: mutex inev locking...\n", pself);
+#endif
assert(locked_by != pself);
pthread_mutex_lock(&mutex_inevitable);
locked_by = pself;
+#ifdef RPY_STM_DEBUG_PRINT
if (PYPY_HAVE_DEBUG_PRINTS) fprintf(PYPY_DEBUG_FILE,
"%lx: mutex inev locked\n", pself);
+#endif
}
static void mutex_unlock(void)
{
unsigned long pself = (unsigned long)pthread_self();
locked_by = 0;
+#ifdef RPY_STM_DEBUG_PRINT
if (PYPY_HAVE_DEBUG_PRINTS) fprintf(PYPY_DEBUG_FILE,
"%lx: mutex inev unlocked\n", pself);
+#endif
pthread_mutex_unlock(&mutex_inevitable);
}
# else
@@ -431,6 +444,10 @@
not_found:;
}
+ // XXX try to remove this check from the main path
+ if (is_main_thread(d))
+ return *(long *)(((char *)addr) + offset);
+
retry:
// read the orec BEFORE we read anything else
ovt = o->version;
@@ -465,7 +482,7 @@
}
-static struct tx_descriptor *descriptor_init(void)
+static struct tx_descriptor *descriptor_init(_Bool is_main_thread)
{
assert(thread_descriptor == NULL);
if (1) /* for hg diff */
@@ -477,11 +494,18 @@
PYPY_DEBUG_START("stm-init");
#endif
- /* initialize 'my_lock_word' to be a unique negative number */
- d->my_lock_word = (owner_version_t)d;
- if (!IS_LOCKED(d->my_lock_word))
- d->my_lock_word = ~d->my_lock_word;
- assert(IS_LOCKED(d->my_lock_word));
+ if (is_main_thread)
+ {
+ d->my_lock_word = 0;
+ }
+ else
+ {
+ /* initialize 'my_lock_word' to be a unique negative number */
+ d->my_lock_word = (owner_version_t)d;
+ if (!IS_LOCKED(d->my_lock_word))
+ d->my_lock_word = ~d->my_lock_word;
+ assert(IS_LOCKED(d->my_lock_word));
+ }
/*d->spinloop_counter = (unsigned int)(d->my_lock_word | 1);*/
thread_descriptor = d;
@@ -549,6 +573,7 @@
static long commit_transaction(void)
{
struct tx_descriptor *d = thread_descriptor;
+ assert(!is_main_thread(d));
// if I don't have writes, I'm committed
if (!redolog_any_entry(&d->redolog))
@@ -707,11 +732,10 @@
}
-void stm_set_tls(void *newtls, long (*getsize)(void*))
+void stm_set_tls(void *newtls, long is_main_thread)
{
- struct tx_descriptor *d = descriptor_init();
+ struct tx_descriptor *d = descriptor_init(is_main_thread);
d->rpython_tls_object = newtls;
- d->rpython_get_size = getsize;
}
void *stm_get_tls(void)
@@ -752,4 +776,9 @@
} REDOLOG_LOOP_END;
}
+void stm_setup_size_getter(long(*getsize_fn)(void*))
+{
+ rpython_get_size = getsize_fn;
+}
+
#endif /* PYPY_NOT_MAIN_FILE */
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -12,7 +12,9 @@
#include "src/commondefs.h"
-void stm_set_tls(void *, long(*)(void*));
+void stm_setup_size_getter(long(*)(void*));
+
+void stm_set_tls(void *, long);
void *stm_get_tls(void);
void stm_del_tls(void);
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -14,7 +14,10 @@
def _freeze_(self):
return True
- set_tls = smexternal('stm_set_tls', [llmemory.Address, GETSIZE],
+ setup_size_getter = smexternal('stm_setup_size_getter', [GETSIZE],
+ lltype.Void)
+
+ set_tls = smexternal('stm_set_tls', [llmemory.Address, lltype.Signed],
lltype.Void)
get_tls = smexternal('stm_get_tls', [], llmemory.Address)
del_tls = smexternal('stm_del_tls', [], lltype.Void)
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
@@ -2,17 +2,22 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.annlowlevel import llhelper
from pypy.translator.stm.stmgcintf import StmOperations, CALLBACK, GETSIZE
+from pypy.rpython.memory.gc import stmgc
stm_operations = StmOperations()
DEFAULT_TLS = lltype.Struct('DEFAULT_TLS')
+S1 = lltype.Struct('S1', ('hdr', stmgc.StmGC.HDR),
+ ('x', lltype.Signed),
+ ('y', lltype.Signed))
+
def test_set_get_del():
# assume that they are really thread-local; not checked here
s = lltype.malloc(lltype.Struct('S'), flavor='raw')
a = llmemory.cast_ptr_to_adr(s)
- stm_operations.set_tls(a, lltype.nullptr(GETSIZE.TO))
+ stm_operations.set_tls(a, 1)
assert stm_operations.get_tls() == a
stm_operations.del_tls()
lltype.free(s, flavor='raw')
@@ -25,15 +30,12 @@
s = lltype.malloc(TLS, flavor='raw', immortal=True)
self.tls = s
a = llmemory.cast_ptr_to_adr(s)
- getsize = llhelper(GETSIZE, self.getsize)
- stm_operations.set_tls(a, getsize)
+ in_main_thread = getattr(meth, 'in_main_thread', True)
+ stm_operations.set_tls(a, int(in_main_thread))
def teardown_method(self, meth):
stm_operations.del_tls()
- def getsize(self, obj):
- xxx
-
def test_set_get_del(self):
a = llmemory.cast_ptr_to_adr(self.tls)
assert stm_operations.get_tls() == a
@@ -80,3 +82,46 @@
p_callback, seen = self.get_callback()
stm_operations.tldict_enum(p_callback)
assert seen == []
+
+ def stm_read_case(self, flags, copied=False):
+ # doesn't test STM behavior, but just that it appears to work
+ s1 = lltype.malloc(S1, flavor='raw')
+ s1.hdr.tid = stmgc.GCFLAG_GLOBAL | flags
+ s1.hdr.version = llmemory.NULL
+ s1.x = 42042
+ if copied:
+ s2 = lltype.malloc(S1, flavor='raw')
+ s2.hdr.tid = stmgc.GCFLAG_WAS_COPIED
+ s2.hdr.version = llmemory.NULL
+ s2.x = 84084
+ a1 = llmemory.cast_ptr_to_adr(s1)
+ a2 = llmemory.cast_ptr_to_adr(s2)
+ stm_operations.tldict_add(a1, a2)
+ res = stm_operations.stm_read_word(llmemory.cast_ptr_to_adr(s1),
+ rffi.sizeof(S1.hdr)) # 'x'
+ lltype.free(s1, flavor='raw')
+ if copied:
+ lltype.free(s2, flavor='raw')
+ return res
+
+ def test_stm_read_word_main_thread(self):
+ res = self.stm_read_case(0) # not copied
+ assert res == 42042
+ res = self.stm_read_case(stmgc.GCFLAG_WAS_COPIED) # but ignored
+ assert res == 42042
+
+ def test_stm_read_word_transactional_thread(self):
+ res = self.stm_read_case(0) # not copied
+ assert res == 42042
+ res = self.stm_read_case(stmgc.GCFLAG_WAS_COPIED) # but ignored
+ assert res == 42042
+ res = self.stm_read_case(stmgc.GCFLAG_WAS_COPIED, copied=True)
+ assert res == 84084
+ test_stm_read_word_transactional_thread.in_main_thread = False
+
+ def test_stm_size_getter(self):
+ def getsize(addr):
+ xxx
+ getter = llhelper(GETSIZE, getsize)
+ stm_operations.setup_size_getter(getter)
+ # just tests that the function is really defined
More information about the pypy-commit
mailing list