Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r1656:a4584a403dd7 Date: 2015-02-24 16:52 +0100 http://bitbucket.org/pypy/stmgc/changeset/a4584a403dd7/
Log: merge heads diff --git a/c8/stm/extra.c b/c8/stm/extra.c --- a/c8/stm/extra.c +++ b/c8/stm/extra.c @@ -6,15 +6,24 @@ static long register_callbacks(stm_thread_local_t *tl, void *key, void callback(void *), long index) { - if (!_stm_in_transaction(tl)) { - /* check that the current thread-local is really running a + dprintf(("register_callbacks: tl=%p key=%p callback=%p index=%ld\n", + tl, key, callback, index)); + if (tl->associated_segment_num == -1) { + /* check that the provided thread-local is really running a transaction, and do nothing otherwise. */ + dprintf((" NOT IN TRANSACTION\n")); return -1; } - - if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) { + /* The tl was only here to check that. We're really using + STM_PSEGMENT below, which is often but not always the + segment corresponding to the tl. One case where it's not + the case is if this gets called from stmcb_light_finalizer() + from abort_finalizers() from major collections or contention. + */ + if (STM_PSEGMENT->transaction_state != TS_REGULAR) { /* ignore callbacks if we're in an inevitable transaction - (which cannot abort) */ + (which cannot abort) or no transaction at all in this segment */ + dprintf((" STATE = %d\n", (int)STM_PSEGMENT->transaction_state)); return -1; } @@ -23,15 +32,19 @@ if (callback == NULL) { /* double-unregistering works, but return 0 */ - return tree_delete_item(callbacks, (uintptr_t)key); + long res = tree_delete_item(callbacks, (uintptr_t)key); + dprintf((" DELETED %ld\n", res)); + return res; } else { /* double-registering the same key will crash */ + dprintf((" INSERTING\n")); tree_insert(callbacks, (uintptr_t)key, (uintptr_t)callback); return 1; } } + long stm_call_on_commit(stm_thread_local_t *tl, void *key, void callback(void *)) { @@ -39,6 +52,7 @@ if (result < 0 && callback != NULL) { /* no regular transaction running, invoke the callback immediately */ + dprintf(("stm_call_on_commit calls now: %p(%p)\n", callback, key)); callback(key); } return result; @@ -72,8 +86,11 @@ assert(key != NULL); assert(callback != NULL); - /* The callback may call stm_call_on_abort(key, NULL). It is ignored, - because 'callbacks_on_commit_and_abort' was cleared already. */ + /* The callback may call stm_call_on_abort(key, NULL) + (so with callback==NULL). It is ignored, because + 'callbacks_on_commit_and_abort' was cleared already. */ + dprintf(("invoke_and_clear_user_callbacks(%ld): %p(%p)\n", + index, callback, key)); callback(key); } TREE_LOOP_END; diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c --- a/c8/stm/gcpage.c +++ b/c8/stm/gcpage.c @@ -388,10 +388,10 @@ */ /* only for new, uncommitted objects: - If 'tl' is currently running, its 'associated_segment_num' + If 'tl' is currently running, its 'last_associated_segment_num' field is the segment number that contains the correct version of its overflowed objects. */ - char *segment_base = get_segment_base(tl->associated_segment_num); + char *segment_base = get_segment_base(tl->last_associated_segment_num); struct stm_shadowentry_s *current = tl->shadowstack; struct stm_shadowentry_s *base = tl->shadowstack_base; diff --git a/c8/stm/setup.c b/c8/stm/setup.c --- a/c8/stm/setup.c +++ b/c8/stm/setup.c @@ -223,14 +223,15 @@ tl->prev = stm_all_thread_locals->prev; stm_all_thread_locals->prev->next = tl; stm_all_thread_locals->prev = tl; - num = (tl->prev->associated_segment_num) % (NB_SEGMENTS-1); + num = (tl->prev->last_associated_segment_num) % (NB_SEGMENTS-1); } tl->thread_local_obj = NULL; /* assign numbers consecutively, but that's for tests; we could also assign the same number to all of them and they would get their own numbers automatically. */ - tl->associated_segment_num = num + 1; + tl->associated_segment_num = -1; + tl->last_associated_segment_num = num + 1; *_get_cpth(tl) = pthread_self(); _init_shadow_stack(tl); set_gs_register(get_segment_base(num + 1)); diff --git a/c8/stm/sync.c b/c8/stm/sync.c --- a/c8/stm/sync.c +++ b/c8/stm/sync.c @@ -110,7 +110,7 @@ assert(_has_mutex()); assert(_is_tl_registered(tl)); - int num = tl->associated_segment_num - 1; // 0..NB_SEG-1 + int num = tl->last_associated_segment_num - 1; // 0..NB_SEG-1 OPT_ASSERT(num >= 0); if (sync_ctl.in_use1[num+1] == 0) { /* fast-path: we can get the same segment number than the one @@ -130,8 +130,9 @@ num = (num+1) % (NB_SEGMENTS-1); if (sync_ctl.in_use1[num+1] == 0) { /* we're getting 'num', a different number. */ - dprintf(("acquired different segment: %d->%d\n", tl->associated_segment_num, num+1)); - tl->associated_segment_num = num+1; + dprintf(("acquired different segment: %d->%d\n", + tl->last_associated_segment_num, num+1)); + tl->last_associated_segment_num = num+1; set_gs_register(get_segment_base(num+1)); goto got_num; } @@ -147,6 +148,7 @@ sync_ctl.in_use1[num+1] = 1; assert(STM_SEGMENT->segment_num == num+1); assert(STM_SEGMENT->running_thread == NULL); + tl->associated_segment_num = tl->last_associated_segment_num; STM_SEGMENT->running_thread = tl; return true; } @@ -158,10 +160,12 @@ cond_signal(C_SEGMENT_FREE); assert(STM_SEGMENT->running_thread == tl); + assert(tl->associated_segment_num == tl->last_associated_segment_num); + tl->associated_segment_num = -1; STM_SEGMENT->running_thread = NULL; - assert(sync_ctl.in_use1[tl->associated_segment_num] == 1); - sync_ctl.in_use1[tl->associated_segment_num] = 0; + assert(sync_ctl.in_use1[tl->last_associated_segment_num] == 1); + sync_ctl.in_use1[tl->last_associated_segment_num] = 0; } __attribute__((unused)) @@ -172,9 +176,16 @@ bool _stm_in_transaction(stm_thread_local_t *tl) { - int num = tl->associated_segment_num; - assert(1 <= num && num < NB_SEGMENTS); - return get_segment(num)->running_thread == tl; + if (tl->associated_segment_num == -1) { + return false; + } + else { + int num = tl->associated_segment_num; + OPT_ASSERT(1 <= num && num < NB_SEGMENTS); + OPT_ASSERT(num == tl->last_associated_segment_num); + OPT_ASSERT(get_segment(num)->running_thread == tl); + return true; + } } void _stm_test_switch(stm_thread_local_t *tl) diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -67,6 +67,7 @@ long last_abort__bytes_in_nursery; /* the next fields are handled internally by the library */ int associated_segment_num; + int last_associated_segment_num; struct stm_thread_local_s *prev, *next; void *creating_pthread[2]; } stm_thread_local_t; _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit