Author: Armin Rigo <ar...@tunes.org>
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
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to