Author: Remi Meier <remi.me...@gmail.com> Branch: Changeset: r1994:bfbab11bd95f Date: 2016-07-07 14:14 +0200 http://bitbucket.org/pypy/stmgc/changeset/bfbab11bd95f/
Log: fix for previously committed test and do some more resetting After an in-validation-reset of a noconflict obj, the obj was still marked as having been read before. Also, an obj with cards is not in old_objects_with_cards_set anymore after a collection. Thus we should clear all cards unconditionally during a reset. diff --git a/c8/stm/core.c b/c8/stm/core.c --- a/c8/stm/core.c +++ b/c8/stm/core.c @@ -233,7 +233,7 @@ for (; undo < end; undo++) { object_t *obj; - if (undo->type != TYPE_POSITION_MARKER) { + if (LIKELY(undo->type != TYPE_POSITION_MARKER)) { /* common case: 'undo->object' was written to in this past commit, so we must check that it was not read by us. */ @@ -263,7 +263,10 @@ an abort. However, from now on, we also assume that an abort would not roll-back to what is in the backup copy, as we don't trace the bkcpy - during major GCs. + during major GCs. (Seg0 may contain the version + found in the other segment and thus not have to + content of our bk_copy) + We choose the approach to reset all our changes to this obj here, so that we can throw away the backup copy completely: */ @@ -396,11 +399,15 @@ */ static void _validate_and_attach(struct stm_commit_log_entry_s *new) { + uintptr_t cle_length = 0; struct stm_commit_log_entry_s *old; OPT_ASSERT(new != NULL); OPT_ASSERT(new != INEV_RUNNING); + cle_length = list_count(STM_PSEGMENT->modified_old_objects); + assert(cle_length == new->written_count * 3); + soon_finished_or_inevitable_thread_segment(); retry_from_start: @@ -409,6 +416,16 @@ stm_abort_transaction(); } + if (cle_length != list_count(STM_PSEGMENT->modified_old_objects)) { + /* something changed the list of modified objs during _stm_validate; or + * during a major GC that also does _stm_validate(). That "something" + * can only be a reset of a noconflict obj. Thus, we recreate the CL + * entry */ + free_cle(new); + new = _create_commit_log_entry(); + cle_length = list_count(STM_PSEGMENT->modified_old_objects); + } + #if STM_TESTS if (STM_PSEGMENT->transaction_state != TS_INEVITABLE && STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) { @@ -607,6 +624,10 @@ size_t start_offset; if (first_call) { start_offset = 0; + + /* flags like a never-touched obj */ + assert(obj->stm_flags & GCFLAG_WRITE_BARRIER); + assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED)); } else { start_offset = -1; } @@ -1288,10 +1309,21 @@ reset_modified_from_backup_copies(segment_num, obj); + /* reset read marker (must not be considered read either) */ + ((struct stm_read_marker_s *) + (pseg->pub.segment_base + (((uintptr_t)obj) >> 4)))->rm = 0; + + /* reset possibly marked cards */ + if (get_page_status_in(segment_num, (uintptr_t)obj / 4096) == PAGE_ACCESSIBLE + && obj_should_use_cards(pseg->pub.segment_base, obj)) { + /* if header is not accessible, we didn't mark any cards */ + _reset_object_cards(pseg, obj, CARD_CLEAR, false, false); + } + + /* remove from all other lists */ LIST_FOREACH_R(pseg->old_objects_with_cards_set, object_t * /*item*/, { if (item == obj) { - _reset_object_cards(pseg, item, CARD_CLEAR, false, false); /* copy last element over this one (HACK) */ _lst->count -= 1; _lst->items[_i] = _lst->items[_lst->count]; @@ -1330,7 +1362,7 @@ continue; object_t *obj = undo->object; - if (only_obj != NULL && obj != only_obj) + if (UNLIKELY(only_obj != NULL) && LIKELY(obj != only_obj)) continue; char *dst = REAL_ADDRESS(pseg->pub.segment_base, obj); @@ -1345,17 +1377,15 @@ free_bk(undo); - if (only_obj != NULL) { - /* WB_EXECUTED should be set on small objs, but not on card objs */ - assert(IMPLY(only_obj != NULL, - (((struct object_s *)dst)->stm_flags - & GCFLAG_NO_CONFLICT))); + if (UNLIKELY(only_obj != NULL)) { + assert(((struct object_s *)dst)->stm_flags & GCFLAG_NO_CONFLICT); + /* copy last element over this one */ end--; list->count -= 3; - if (undo < end) - *undo = *end; - undo--; /* next itr */ + *undo = *end; + /* to neutralise the increment for the next iter: */ + undo--; } } @@ -1664,13 +1694,13 @@ assert(STM_PSEGMENT->privatization_lock); assert(obj->stm_flags & GCFLAG_WRITE_BARRIER); assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED)); + assert(!(obj->stm_flags & GCFLAG_CARDS_SET)); ssize_t obj_size = stmcb_size_rounded_up( (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj)); OPT_ASSERT(obj_size >= 16); if (LIKELY(is_small_uniform(obj))) { - assert(!(obj->stm_flags & GCFLAG_CARDS_SET)); OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE); _synchronize_fragment((stm_char *)obj, obj_size); return; diff --git a/c8/test/test_noconfl.py b/c8/test/test_noconfl.py --- a/c8/test/test_noconfl.py +++ b/c8/test/test_noconfl.py @@ -175,6 +175,8 @@ stm_set_char(o, 'a') stm_set_char(oh, 'x', use_cards=True) + assert stm_was_read(o) + assert stm_was_read(oh) assert o in modified_old_objects() assert oh in modified_old_objects() assert o in objects_pointing_to_nursery() @@ -189,6 +191,8 @@ self.commit_transaction() self.switch(0, False) + assert stm_was_read(o) + assert stm_was_read(oh) assert stm_get_char(o) == 'a' assert stm_get_char(oh) == 'x' assert o in modified_old_objects() @@ -197,6 +201,8 @@ assert oh not in objects_pointing_to_nursery() assert oh in old_objects_with_cards_set() stm_validate() + assert not stm_was_read(o) + assert not stm_was_read(oh) assert stm_get_char(o) == 'b' assert stm_get_char(oh) == 'y' assert o not in modified_old_objects() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit