[pypy-commit] pypy stmgc-c8: import stmgc with fixes for noconfl objs
Raemi
pypy.commits at gmail.com
Thu Jul 7 08:17:50 EDT 2016
Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c8
Changeset: r85598:c458e253bab4
Date: 2016-07-07 14:16 +0200
http://bitbucket.org/pypy/pypy/changeset/c458e253bab4/
Log: import stmgc with fixes for noconfl objs
diff --git a/rpython/translator/stm/src_stm/revision b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-5e3551b4e599
+bfbab11bd95f+
diff --git a/rpython/translator/stm/src_stm/stm/core.c b/rpython/translator/stm/src_stm/stm/core.c
--- a/rpython/translator/stm/src_stm/stm/core.c
+++ b/rpython/translator/stm/src_stm/stm/core.c
@@ -151,6 +151,7 @@
}
static void reset_modified_from_backup_copies(int segment_num, object_t *only_obj); /* forward */
+static void undo_modifications_to_single_obj(int segment_num, object_t *only_obj); /* forward */
static bool _stm_validate(void)
{
@@ -232,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. */
@@ -262,13 +263,17 @@
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: */
/* XXX: this browses through the whole list of modified
fragments; this may become a problem... */
- reset_modified_from_backup_copies(my_segnum, obj);
+ undo_modifications_to_single_obj(my_segnum, obj);
+
continue;
}
@@ -394,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:
@@ -407,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) {
@@ -605,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;
}
@@ -1276,6 +1299,48 @@
invoke_general_finalizers(tl);
}
+static void undo_modifications_to_single_obj(int segment_num, object_t *obj)
+{
+ /* special function used for noconflict objs to reset all their
+ * modifications and make them appear untouched in the current transaction.
+ * I.e., reset modifications and remove from all lists. */
+
+ struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
+
+ 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) {
+ /* copy last element over this one (HACK) */
+ _lst->count -= 1;
+ _lst->items[_i] = _lst->items[_lst->count];
+ break;
+ }
+ });
+ LIST_FOREACH_R(pseg->objects_pointing_to_nursery, object_t * /*item*/,
+ {
+ if (item == obj) {
+ /* copy last element over this one (HACK) */
+ _lst->count -= 1;
+ _lst->items[_i] = _lst->items[_lst->count];
+ break;
+ }
+ });
+}
+
static void reset_modified_from_backup_copies(int segment_num, object_t *only_obj)
{
#pragma push_macro("STM_PSEGMENT")
@@ -1284,6 +1349,9 @@
#undef STM_SEGMENT
assert(modification_lock_check_wrlock(segment_num));
+ /* WARNING: resetting the obj will remove the WB flag. Make sure you either
+ * re-add it or remove it from lists where it was added based on the flag. */
+
struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
struct list_s *list = pseg->modified_old_objects;
struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
@@ -1294,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);
@@ -1309,19 +1377,15 @@
free_bk(undo);
- if (only_obj != NULL) {
- assert(IMPLY(only_obj != NULL,
- (((struct object_s *)dst)->stm_flags
- & (GCFLAG_NO_CONFLICT
- | GCFLAG_WRITE_BARRIER
- | GCFLAG_WB_EXECUTED))
- == (GCFLAG_NO_CONFLICT | GCFLAG_WRITE_BARRIER)));
+ 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--;
}
}
@@ -1630,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/rpython/translator/stm/src_stm/stm/nursery.c b/rpython/translator/stm/src_stm/stm/nursery.c
--- a/rpython/translator/stm/src_stm/stm/nursery.c
+++ b/rpython/translator/stm/src_stm/stm/nursery.c
@@ -118,6 +118,9 @@
char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj);
memcpy(realnobj, realobj, size);
+ /* uint64_t ttt = 0xa0a0a0a0a0a0a0a0; */
+ /* assert(memmem(realobj, size, &ttt, sizeof(uint64_t)) == NULL); */
+
nobj_sync_now = ((uintptr_t)nobj) | FLAG_SYNC_LARGE;
pforwarded_array[0] = GCWORD_MOVED;
diff --git a/rpython/translator/stm/src_stm/stmgc.h b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -205,7 +205,7 @@
threads than the number of segments, it will block, waiting for the
next segment to become free.
*/
-#define STM_NB_SEGMENTS 4
+#define STM_NB_SEGMENTS 8
/* Structure of objects
--------------------
More information about the pypy-commit
mailing list