[pypy-commit] stmgc c8-new-page-handling: in-progress

arigo noreply at buildbot.pypy.org
Tue Sep 23 20:00:50 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: c8-new-page-handling
Changeset: r1413:68c788b03b94
Date: 2014-09-23 20:00 +0200
http://bitbucket.org/pypy/stmgc/changeset/68c788b03b94/

Log:	in-progress

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -4,54 +4,28 @@
 
 
 /* ############# signal handler ############# */
-static void memcpy_to_accessible_pages(
-    int dst_segnum, object_t *dst_obj,
-    char *src, size_t len, uintptr_t only_page)
-{
-    /* XXX: optimize */
-
-    char *realobj = REAL_ADDRESS(get_segment_base(dst_segnum), dst_obj);
-    char *dst_end = realobj + len;
-    uintptr_t loc_addr = (uintptr_t)dst_obj;
-
-    dprintf(("memcpy_to_accessible_pages(%d, %p, %p, %lu, %lu)\n",
-             dst_segnum, dst_obj, src, len, only_page));
-
-    while (realobj != dst_end) {
-        if (get_page_status_in(dst_segnum, loc_addr / 4096UL) != PAGE_NO_ACCESS
-            && (only_page == -1 || only_page == loc_addr / 4096UL)) {
-            *realobj = *src;
-        }
-        realobj++;
-        loc_addr++;
-        src++;
-    }
-}
-
 
 static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum)
 {
     /* looks at all bk copies of objects overlapping page 'pagenum' and
-       copies to current segment (never touch PROT_NONE memory). */
+       copies the part in 'pagenum' back to the current segment */
     dprintf(("copy_bk_objs_in_page_from(%d, %lu)\n", from_segnum, pagenum));
 
     acquire_modified_objs_lock(from_segnum);
-    abort();
-    struct tree_s *tree = NULL; // get_priv_segment(from_segnum)->modified_old_objects;
-    wlog_t *item;
-    TREE_LOOP_FORWARD(tree, item); {
-        object_t *obj = (object_t*)item->addr;
-        struct object_s* bk_obj = (struct object_s *)item->val;
-        size_t obj_size = stmcb_size_rounded_up(bk_obj);
+    struct list_s *list = get_priv_segment(from_segnum)->modified_old_objects;
+    struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
+    struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
-        if (item->addr < (pagenum + 1) * 4096UL && item->addr + obj_size > pagenum * 4096UL) {
-            /* XXX: should actually only write to pagenum, but we validate
-               afterwards anyway and abort in case we had modifications there */
-            memcpy_to_accessible_pages(STM_SEGMENT->segment_num,
-                                       obj, (char*)bk_obj, obj_size, pagenum);
+    for (; undo < end; undo++) {
+        object_t *obj = undo->object;
+        stm_char *oslice = ((stm_char *)obj) + SLICE_OFFSET(undo->slice);
+        uintptr_t current_page_num = ((uintptr_t)oslice) / 4096;
+
+        if (current_page_num == pagenum) {
+            char *dst = REAL_ADDRESS(STM_SEGMENT->segment_base, oslice);
+            memcpy(dst, undo->backup, SLICE_SIZE(undo->slice));
         }
-    } TREE_LOOP_END;
-
+    }
     release_modified_objs_lock(from_segnum);
 }
 
@@ -129,10 +103,12 @@
     /* if there were modifications in the page, revert them: */
     copy_bk_objs_in_page_from(shared_page_holder, pagenum);
 
-    /* if not already newer, update page to our revision */
-    update_page_revision_from_to(
-        pagenum, get_priv_segment(shared_page_holder)->last_commit_log_entry,
-        STM_PSEGMENT->last_commit_log_entry);
+    /* Note that we can't really read without careful locking
+       'get_priv_segment(shared_page_holder)->last_commit_log_entry'.
+       Instead, we're just assuming that the current status of the
+       page is xxxxxxxxxxxxxxx
+    */
+    abort();
 
     /* in case page is already newer, validate everything now to have a common
        revision for all pages */
@@ -210,21 +186,16 @@
     stm_char *slice_end = slice_start + size;
 
     uintptr_t page_start = ((uintptr_t)slice_start) / 4096;
-    if ((uintptr_t)slice_end <= (page_start + 1) * 4096) {
+    assert((uintptr_t)slice_end <= (page_start + 1) * 4096);
 
-        /* the object fits inside a single page: fast path */
-        if (get_page_status_in(STM_SEGMENT->segment_num, page_start)
+    if (get_page_status_in(STM_SEGMENT->segment_num, page_start)
             == PAGE_NO_ACCESS) {
-            return;   /* ignore the object: it is in a NO_ACCESS page */
-        }
+        return;   /* ignore the object: it is in a NO_ACCESS page */
+    }
 
-        char *src = undo->backup;
-        char *dst = REAL_ADDRESS(STM_SEGMENT->segment_base, slice_start);
-        memcpy(dst, src, size);
-    }
-    else {
-        abort(); //XXX
-    }
+    char *src = undo->backup;
+    char *dst = REAL_ADDRESS(STM_SEGMENT->segment_base, slice_start);
+    memcpy(dst, src, size);
 }
 
 static void reset_modified_from_backup_copies(int segment_num);  /* forward */
@@ -342,6 +313,10 @@
     else {
         _validate_and_attach(new);
     }
+
+    acquire_modified_objs_lock(STM_SEGMENT->segment_num);
+    list_clear(STM_PSEGMENT->modified_old_objects);
+    release_modified_objs_lock(STM_SEGMENT->segment_num);
 }
 
 /* ############# STM ############# */
@@ -377,31 +352,38 @@
     dprintf(("write_slowpath(%p): sz=%lu, bk=%p\n", obj, obj_size, bk_obj));
  retry:
     /* privatize pages: */
+    /* XXX don't always acquire all locks... */
     acquire_all_privatization_locks();
 
     uintptr_t page;
     for (page = first_page; page <= end_page; page++) {
         /* check if our page is private or we are the only shared-page holder */
-        if (get_page_status_in(my_segnum, page) == PAGE_NO_ACCESS) {
+        switch (get_page_status_in(my_segnum, page)) {
+
+        case PAGE_PRIVATE:
+            continue;
+
+        case PAGE_NO_ACCESS:
             /* happens if there is a concurrent WB between us making the backup
                and acquiring the locks */
             release_all_privatization_locks();
 
             volatile char *dummy = REAL_ADDRESS(STM_SEGMENT->segment_base, page * 4096UL);
-            *dummy = *dummy;            /* force segfault */
+            *dummy;            /* force segfault */
 
             goto retry;
+
+        case PAGE_SHARED:
+            break;
+
+        default:
+            assert(0);
         }
-        assert(get_page_status_in(my_segnum, page) != PAGE_NO_ACCESS);
-
-        if (get_page_status_in(my_segnum, page) == PAGE_PRIVATE)
-            continue;
-
-        assert(get_page_status_in(my_segnum, page) == PAGE_SHARED);
         /* make sure all the others are NO_ACCESS
            choosing to make us PRIVATE is harder because then nobody must ever
            update the shared page in stm_validate() except if it is the sole
            reader of it. But then we don't actually know which revision the page is at. */
+        /* XXX this is a temporary solution I suppose */
         int i;
         for (i = 0; i < NB_SEGMENTS; i++) {
             if (i == my_segnum)
@@ -426,15 +408,24 @@
 
     /* phew, now add the obj to the write-set and register the
        backup copy. */
-    /* XXX: possibly slow check; try overflow objs again? */
-    abort();
-    /*if (!tree_contains(STM_PSEGMENT->modified_old_objects, (uintptr_t)obj)) {
-        acquire_modified_objs_lock(my_segnum);
-        tree_insert(STM_PSEGMENT->modified_old_objects,
-                    (uintptr_t)obj, (uintptr_t)bk_obj);
-        release_modified_objs_lock(my_segnum);
-    }*/
-    /* XXX else... what occurs with bk_obj? */
+    /* XXX: we should not be here at all fiddling with page status
+       if 'obj' is merely an overflow object.  FIX ME, likely by copying
+       the overflow number logic from c7. */
+
+    assert(first_page == end_page);  /* XXX! */
+    /* XXX do the case where first_page != end_page in pieces.  Maybe also
+       use mprotect() again to mark pages of the object as read-only, and
+       only stick it into modified_old_objects page-by-page?  Maybe it's
+       possible to do card-marking that way, too. */
+
+    uintptr_t slice = obj_size;
+    assert(SLICE_OFFSET(slice) == 0 && SLICE_SIZE(slice) == obj_size);
+
+    acquire_modified_objs_lock(STM_SEGMENT->segment_num);
+    STM_PSEGMENT->modified_old_objects = list_append3(
+        STM_PSEGMENT->modified_old_objects,
+        (uintptr_t)obj, (uintptr_t)bk_obj, slice);
+    release_modified_objs_lock(STM_SEGMENT->segment_num);
 
     /* done fiddling with protection and privatization */
     release_all_privatization_locks();
@@ -604,7 +595,7 @@
 #pragma push_macro("STM_SEGMENT")
 #undef STM_PSEGMENT
 #undef STM_SEGMENT
-    //acquire_modified_objs_lock(segment_num);
+    acquire_modified_objs_lock(segment_num);
 
     struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
     struct list_s *list = pseg->modified_old_objects;
@@ -626,7 +617,7 @@
 
     list_clear(list);
 
-    //release_modified_objs_lock(segment_num);
+    release_modified_objs_lock(segment_num);
 
 #pragma pop_macro("STM_SEGMENT")
 #pragma pop_macro("STM_PSEGMENT")
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -102,10 +102,9 @@
 struct stm_undo_s {
     object_t *object;   /* the object that is modified */
     char *backup;       /* some backup data (a slice of the original obj) */
-    uint64_t slice;     /* location and size of this slice (== the whole
-                           object, unless card marking is enabled).  The
-                           size is in the lower 2 bytes, and the offset
-                           in the remaining 6 bytes. */
+    uint64_t slice;     /* location and size of this slice (cannot cross
+                           pages).  The size is in the lower 2 bytes, and
+                           the offset in the remaining 6 bytes. */
 };
 #define SLICE_OFFSET(slice)  ((slice) >> 16)
 #define SLICE_SIZE(slice)    ((int)((slice) & 0xFFFF))
@@ -181,7 +180,6 @@
 
 static inline void acquire_modified_objs_lock(int segnum)
 {
-    /* XXX no longer neeeded? */
     spinlock_acquire(get_priv_segment(segnum)->modified_objs_lock);
 }
 
diff --git a/c8/stm/list.h b/c8/stm/list.h
--- a/c8/stm/list.h
+++ b/c8/stm/list.h
@@ -45,6 +45,19 @@
     return lst;
 }
 
+static inline struct list_s *list_append3(struct list_s *lst, uintptr_t item0,
+                                          uintptr_t item1, uintptr_t item2)
+{
+    uintptr_t index = lst->count;
+    lst->count += 3;
+    if (UNLIKELY(index + 2 > lst->last_allocated))
+        lst = _list_grow(lst, index + 2);
+    lst->items[index + 0] = item0;
+    lst->items[index + 1] = item1;
+    lst->items[index + 2] = item2;
+    return lst;
+}
+
 
 static inline void list_clear(struct list_s *lst)
 {


More information about the pypy-commit mailing list