Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r1616:65a89cd8a6c0 Date: 2015-02-09 19:11 +0100 http://bitbucket.org/pypy/stmgc/changeset/65a89cd8a6c0/
Log: fix the read-write conflict location in case of a conflict between a stmdict.keys() and a write of an entry diff --git a/c7/stm/core.c b/c7/stm/core.c --- a/c7/stm/core.c +++ b/c7/stm/core.c @@ -435,26 +435,31 @@ char *remote_base = get_segment_base(i); object_t *conflicting_obj; + uintptr_t j, limit; + struct list_s *lst; - LIST_FOREACH_R( - STM_PSEGMENT->modified_old_objects, - object_t * /*item*/, - ({ - if (was_read_remote(remote_base, item)) { - conflicting_obj = item; - goto found_conflict; - } - })); + /* Look in forward order: this is an attempt to report the _first_ + write that conflicts with another segment's reads + */ + lst = STM_PSEGMENT->modified_old_objects; + limit = list_count(lst); + for (j = 0; j < limit; j++) { + object_t *obj = (object_t *)list_item(lst, j); + if (was_read_remote(remote_base, obj)) { + conflicting_obj = obj; + goto found_conflict; + } + } - LIST_FOREACH_R( - STM_PSEGMENT->modified_old_hashtables, - object_t * /*item*/, - ({ - if (was_read_remote(remote_base, item)) { - conflicting_obj = item; - goto found_conflict; - } - })); + lst = STM_PSEGMENT->modified_old_hashtables; + limit = list_count(lst); + for (j = 0; j < limit; j += 2) { + object_t *hobj = (object_t *)list_item(lst, j); + if (was_read_remote(remote_base, hobj)) { + conflicting_obj = (object_t *)list_item(lst, j + 1); + goto found_conflict; + } + } continue; diff --git a/c7/stm/core.h b/c7/stm/core.h --- a/c7/stm/core.h +++ b/c7/stm/core.h @@ -96,7 +96,8 @@ uintptr_t modified_old_objects_markers_num_old; /* This list contains all old hashtables that have entries that we - modified. Note that several transactions can all commit if + modified. It's actually a list of pairs hashtable/sample_entry. + Note that several transactions can all commit if they have the same hashtable listed here. The point of this list is only that if another segment does a global "read" of the hashtable (stm_hashtable_list), then it conflicts with this diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c --- a/c7/stm/gcpage.c +++ b/c7/stm/gcpage.c @@ -475,26 +475,13 @@ } } +static void clean_up_segment_lists(void) +{ #pragma push_macro("STM_PSEGMENT") #pragma push_macro("STM_SEGMENT") #undef STM_PSEGMENT #undef STM_SEGMENT -static void remove_objects_that_die(struct list_s *lst) -{ - if (lst != NULL) { - uintptr_t n = list_count(lst); - while (n > 0) { - object_t *obj = (object_t *)list_item(lst, --n); - if (!mark_visited_test(obj)) { - list_set_item(lst, n, list_pop_item(lst)); - } - } - } -} - -static void clean_up_segment_lists(void) -{ long i; for (i = 1; i <= NB_SEGMENTS; i++) { struct stm_priv_segment_info_s *pseg = get_priv_segment(i); @@ -553,14 +540,39 @@ })); list_clear(lst); - /* Remove from 'large_overflow_objects' and 'modified_old_hashtables' - all objects that die */ - remove_objects_that_die(pseg->large_overflow_objects); - remove_objects_that_die(pseg->modified_old_hashtables); + /* Remove from 'large_overflow_objects' all objects that die */ + lst = pseg->large_overflow_objects; + if (lst != NULL) { + uintptr_t n = list_count(lst); + while (n > 0) { + object_t *obj = (object_t *)list_item(lst, --n); + if (!mark_visited_test(obj)) + list_set_item(lst, n, list_pop_item(lst)); + } + } + + /* Remove from 'modified_old_hashtables' all old hashtables that + die, but keeping the order */ + { + lst = pseg->modified_old_hashtables; + uintptr_t j, k = 0, limit = list_count(lst); + for (j = 0; j < limit; j += 2) { + object_t *hobj = (object_t *)list_item(lst, j); + if (mark_visited_test(hobj)) { + /* hobj does not die */ + if (j != k) { + list_set_item(lst, k, (uintptr_t)hobj); + list_set_item(lst, k + 1, list_item(lst, j + 1)); + } + k += 2; + } + } + lst->count = k; + } } -} #pragma pop_macro("STM_SEGMENT") #pragma pop_macro("STM_PSEGMENT") +} static inline bool largemalloc_keep_object_at(char *data) { diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c --- a/c7/stm/hashtable.c +++ b/c7/stm/hashtable.c @@ -358,12 +358,13 @@ avoid them --- at least the list should never be longer than 'modified_old_objects'. */ i = list_count(STM_PSEGMENT->modified_old_hashtables); - if (i > 0 && list_item(STM_PSEGMENT->modified_old_hashtables, i - 1) + if (i > 0 && list_item(STM_PSEGMENT->modified_old_hashtables, i - 2) == (uintptr_t)hobj) { /* already added */ } else { - LIST_APPEND(STM_PSEGMENT->modified_old_hashtables, hobj); + LIST_APPEND2(STM_PSEGMENT->modified_old_hashtables, + hobj, entry); } } } diff --git a/c7/stm/list.h b/c7/stm/list.h --- a/c7/stm/list.h +++ b/c7/stm/list.h @@ -45,6 +45,9 @@ return lst; } +#define LIST_APPEND2(lst, e1, e2) ((lst) = list_append2((lst), \ + (uintptr_t)(e1), (uintptr_t)(e2))) + static inline void list_clear(struct list_s *lst) { _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit