[pypy-commit] stmgc default: fix for previously committed test and do some more resetting
Raemi
pypy.commits at gmail.com
Thu Jul 7 08:17:05 EDT 2016
Author: Remi Meier <remi.meier at 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()
More information about the pypy-commit
mailing list