Author: Armin Rigo <[email protected]>
Branch: c8-hashtable
Changeset: r1718:dc85ba70bb83
Date: 2015-03-12 14:47 +0100
http://bitbucket.org/pypy/stmgc/changeset/dc85ba70bb83/
Log: Remove 'modified_old_hashtables' and use a new variant of
stm_undolog_s.
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -273,8 +273,14 @@
struct stm_undo_s *end = undo + cl->written_count;
for (; undo < end; undo++) {
if (undo->type == TYPE_POSITION_MARKER) {
- fprintf(stderr, " marker %p %lu\n",
- undo->marker_object, undo->marker_odd_number);
+ if (undo->type2 == TYPE_MODIFIED_HASHTABLE) {
+ fprintf(stderr, " hashtable %p\n",
+ undo->modif_hashtable);
+ }
+ else {
+ fprintf(stderr, " marker %p %lu\n",
+ undo->marker_object, undo->marker_odd_number);
+ }
continue;
}
fprintf(stderr, " obj %p, size %d, ofs %lu: ", undo->object,
@@ -376,21 +382,40 @@
struct stm_undo_s *undo = cl->written;
struct stm_undo_s *end = cl->written + cl->written_count;
for (; undo < end; undo++) {
- if (undo->type == TYPE_POSITION_MARKER)
+ object_t *obj;
+
+ if (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. */
+ obj = undo->object;
+ }
+ else if (undo->type2 != TYPE_MODIFIED_HASHTABLE)
continue;
- if (_stm_was_read(undo->object)) {
- /* first reset all modified objects from the backup
- copies as soon as the first conflict is
detected;
- then we will proceed below to update our
segment from
- the old (but unmodified) version to the newer
version.
- */
- reset_modified_from_backup_copies(my_segnum);
- timing_write_read_contention(cl->written, undo);
- needs_abort = true;
+ else {
+ /* the previous stm_undo_s is about a written
+ 'entry' object, which belongs to the hashtable
+ given now. Check that we haven't read the
+ hashtable (via stm_hashtable_list()). */
+ obj = undo->modif_hashtable;
+ }
- dprintf(("_stm_validate() failed for obj %p\n",
undo->object));
- break;
- }
+ if (LIKELY(!_stm_was_read(obj)))
+ continue;
+
+ /* conflict! */
+ dprintf(("_stm_validate() failed for obj %p\n", obj));
+
+ /* first reset all modified objects from the backup
+ copies as soon as the first conflict is detected;
+ then we will proceed below to update our segment
+ from the old (but unmodified) version to the newer
+ version.
+ */
+ reset_modified_from_backup_copies(my_segnum);
+ timing_write_read_contention(cl->written, undo);
+ needs_abort = true;
+ break;
}
}
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -190,9 +190,15 @@
uintptr_t marker_odd_number; /* the odd number part of the marker */
object_t *marker_object; /* the object part of the marker */
};
+ struct {
+ intptr_t type1; /* TYPE_POSITION_MARKER (again) */
+ intptr_t type2; /* TYPE_MODIFIED_HASHTABLE */
+ object_t *modif_hashtable; /* modified entry is previous stm_undo_s */
+ };
};
};
#define TYPE_POSITION_MARKER (-1)
+#define TYPE_MODIFIED_HASHTABLE (-2)
#define SLICE_OFFSET(slice) ((slice) >> 16)
#define SLICE_SIZE(slice) ((int)((slice) & 0xFFFF))
#define NEW_SLICE(offset, size) (((uint64_t)(offset)) << 16 | (size))
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -457,6 +457,7 @@
struct stm_undo_s *modified = (struct stm_undo_s *)lst->items;
struct stm_undo_s *end = (struct stm_undo_s *)(lst->items +
lst->count);
for (; modified < end; modified++) {
+ /* this logic also works if type2 == TYPE_MODIFIED_HASHTABLE */
if (modified->type == TYPE_POSITION_MARKER)
mark_visit_possibly_new_object(modified->marker_object, pseg);
}
diff --git a/c8/stm/hashtable.c b/c8/stm/hashtable.c
--- a/c8/stm/hashtable.c
+++ b/c8/stm/hashtable.c
@@ -351,27 +351,35 @@
void stm_hashtable_write_entry(object_t *hobj, stm_hashtable_entry_t *entry,
object_t *nvalue)
{
- if (stm_write((object_t *)entry)) {
+ if (_STM_WRITE_CHECK_SLOWPATH((object_t *)entry)) {
+
+ stm_write((object_t *)entry);
+
uintptr_t i = list_count(STM_PSEGMENT->modified_old_objects);
- if (i > 0 && list_item(STM_PSEGMENT->modified_old_objects, i - 1)
+ if (i > 0 && list_item(STM_PSEGMENT->modified_old_objects, i - 3)
== (uintptr_t)entry) {
- /* 'modified_old_hashtables' is always obtained by taking
- a subset of 'modified_old_objects' which contains only
- stm_hashtable_entry_t objects, and then replacing the
- stm_hashtable_entry_t objects with the hobj they come
- from. It's possible to have duplicates in
- 'modified_old_hashtables'; here we only try a bit to
- 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 -
2)
- == (uintptr_t)hobj) {
- /* already added */
- }
- else {
- LIST_APPEND2(STM_PSEGMENT->modified_old_hashtables,
- hobj, entry);
- }
+ /* The stm_write() above recorded a write to 'entry'. Here,
+ we add another stm_undo_s to modified_old_objects with
+ TYPE_MODIFIED_HASHTABLE. It is ignored everywhere except
+ in _stm_validate().
+
+ The goal is that this TYPE_MODIFIED_HASHTABLE ends up in
+ the commit log's 'cl_written' array. Later, another
+ transaction validating that log will check two things:
+
+ - the regular stm_undo_s entry put by stm_write() above
+ will make the other transaction check that it didn't
+ read the same 'entry' object;
+
+ - the TYPE_MODIFIED_HASHTABLE entry we're adding now
+ will make the other transaction check that it didn't
+ do any stm_hashtable_list() on the complete hashtable.
+ */
+ STM_PSEGMENT->modified_old_objects = list_append3(
+ STM_PSEGMENT->modified_old_objects,
+ TYPE_POSITION_MARKER, /* type1 */
+ TYPE_MODIFIED_HASHTABLE, /* type2 */
+ (uintptr_t)hobj); /* modif_hashtable */
}
}
entry->object = nvalue;
diff --git a/c8/stm/marker.c b/c8/stm/marker.c
--- a/c8/stm/marker.c
+++ b/c8/stm/marker.c
@@ -42,7 +42,8 @@
*/
while (contention != start) {
--contention;
- if (contention->type == TYPE_POSITION_MARKER) {
+ if (contention->type == TYPE_POSITION_MARKER &&
+ contention->type2 != TYPE_MODIFIED_HASHTABLE) {
out_marker->odd_number = contention->marker_odd_number;
out_marker->object = contention->marker_object;
return;
@@ -69,6 +70,9 @@
return; /* already up-to-date */
}
+ /* -2 is not odd */
+ assert(marker.odd_number != (uintptr_t)TYPE_MODIFIED_HASHTABLE);
+
STM_PSEGMENT->position_markers_last = list_count(list);
STM_PSEGMENT->modified_old_objects = list_append3(
list,
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -422,6 +422,7 @@
struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
for (; undo < end; undo++) {
+ /* this logic also works if type2 == TYPE_MODIFIED_HASHTABLE */
if (undo->type == TYPE_POSITION_MARKER)
minor_trace_if_young(&undo->marker_object);
}
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -192,10 +192,13 @@
STM_SEGMENT->transaction_read_version;
}
+#define _STM_WRITE_CHECK_SLOWPATH(obj) \
+ UNLIKELY(((obj)->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0)
+
__attribute__((always_inline))
static inline void stm_write(object_t *obj)
{
- if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0))
+ if (_STM_WRITE_CHECK_SLOWPATH(obj))
_stm_write_slowpath(obj);
}
@@ -204,7 +207,7 @@
static inline void stm_write_card(object_t *obj, uintptr_t index)
{
/* if GCFLAG_WRITE_BARRIER is set, then don't do anything more. */
- if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0)) {
+ if (_STM_WRITE_CHECK_SLOWPATH(obj)) {
/* GCFLAG_WRITE_BARRIER is not set. This might be because
it's the first time we see a given small array; or it might
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit