Author: Armin Rigo <[email protected]>
Branch:
Changeset: r305:5e0ebfe06495
Date: 2013-06-27 15:28 +0200
http://bitbucket.org/pypy/stmgc/changeset/5e0ebfe06495/
Log: Fix threadlocals.
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -842,6 +842,13 @@
gcptrlist_clear(&d->list_of_read_objects);
g2l_clear(&d->public_to_private);
+ /* 'old_thread_local_obj' contains the old value from stm_thread_local_obj,
+ but only when the transaction can be aborted; when it is inevitable
+ old_thread_local_obj will be reset to NULL. */
+ assert(d->thread_local_obj_ref = &stm_thread_local_obj);
+ stm_thread_local_obj = d->old_thread_local_obj;
+ d->old_thread_local_obj = NULL;
+
/* release the lock */
spinlock_release(d->public_descriptor->collection_lock);
@@ -908,6 +915,7 @@
assert(d->num_private_from_protected_known_old == 0);
assert(d->num_read_objects_known_old == 0);
assert(!g2l_any_entry(&d->public_to_private));
+ assert(d->old_thread_local_obj == NULL);
d->count_reads = 1;
fxcache_clear(&d->recent_reads_cache);
@@ -923,6 +931,7 @@
init_transaction(d);
d->active = 1;
d->setjmp_buf = buf;
+ d->old_thread_local_obj = stm_thread_local_obj;
d->start_time = GetGlobalCurTime(d);
update_reads_size_limit(d);
}
@@ -1250,6 +1259,7 @@
/* we cannot abort any more from here */
d->setjmp_buf = NULL;
+ d->old_thread_local_obj = NULL;
gcptrlist_clear(&d->list_of_read_objects);
dprintf(("\n"
@@ -1282,6 +1292,7 @@
static void make_inevitable(struct tx_descriptor *d)
{
d->setjmp_buf = NULL;
+ d->old_thread_local_obj = NULL;
d->active = 2;
d->reads_size_limit_nonatomic = 0;
update_reads_size_limit(d);
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -136,6 +136,7 @@
gcptr *shadowstack;
gcptr **shadowstack_end_ref;
gcptr *thread_local_obj_ref;
+ gcptr old_thread_local_obj;
NURSERY_FIELDS_DECL
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -341,6 +341,7 @@
/* the thread-local object */
visit(d->thread_local_obj_ref);
+ visit(&d->old_thread_local_obj);
/* the current transaction's private copies of public objects */
wlog_t *item;
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -522,6 +522,7 @@
mark_young_roots(d);
visit_if_young(d->thread_local_obj_ref);
+ visit_if_young(&d->old_thread_local_obj);
mark_stolen_young_stubs(d);
diff --git a/c4/test/test_threadlocal.py b/c4/test/test_threadlocal.py
--- a/c4/test/test_threadlocal.py
+++ b/c4/test/test_threadlocal.py
@@ -33,3 +33,46 @@
lib.stm_finalize()
lib.stm_initialize_tests(0)
assert lib.addr_of_thread_local()[0] == ffi.NULL
+
+def test_threadlocal_commit():
+ p1 = oalloc(HDR)
+ lib.addr_of_thread_local()[0] = p1
+ #
+ @perform_transaction
+ def run(retry_counter):
+ assert retry_counter == 0
+ p2 = nalloc(HDR + 5 * WORD)
+ lib.setlong(p2, 4, -2891922)
+ lib.addr_of_thread_local()[0] = p2
+ #
+ p2b = lib.addr_of_thread_local()[0]
+ assert p2b != p1
+ assert lib.getlong(p2b, 4) == -2891922
+
+def test_threadlocal_abort(case=0):
+ p1 = oalloc(HDR + 5 * WORD)
+ lib.rawsetlong(p1, 4, 38972389)
+ lib.addr_of_thread_local()[0] = p1
+ #
+ @perform_transaction
+ def run(retry_counter):
+ if retry_counter == 0:
+ p2 = nalloc(HDR)
+ lib.addr_of_thread_local()[0] = p2
+ if case == 1:
+ minor_collect()
+ if case == 2:
+ major_collect()
+ abort_and_retry()
+ else:
+ check_not_free(p1)
+ assert lib.addr_of_thread_local()[0] == p1
+ #
+ assert lib.addr_of_thread_local()[0] == p1
+ assert lib.getlong(p1, 4) == 38972389
+
+def test_threadlocal_abort_minor():
+ test_threadlocal_abort(case=1)
+
+def test_threadlocal_abort_major():
+ test_threadlocal_abort(case=2)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit