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