Author: Armin Rigo <[email protected]>
Branch: c8-new-page-handling
Changeset: r1414:d6152847d126
Date: 2014-09-23 20:37 +0200
http://bitbucket.org/pypy/stmgc/changeset/d6152847d126/

Log:    Progress one or two more tests.

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -5,17 +5,9 @@
 
 /* ############# signal handler ############# */
 
-static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum)
+static void _copy_from_undo_log(uintptr_t pagenum, struct stm_undo_s *undo,
+                                struct stm_undo_s *end)
 {
-    /* looks at all bk copies of objects overlapping page 'pagenum' and
-       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);
-    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);
-
     for (; undo < end; undo++) {
         object_t *obj = undo->object;
         stm_char *oslice = ((stm_char *)obj) + SLICE_OFFSET(undo->slice);
@@ -26,40 +18,57 @@
             memcpy(dst, undo->backup, SLICE_SIZE(undo->slice));
         }
     }
-    release_modified_objs_lock(from_segnum);
 }
 
-static void update_page_revision_from_to(uintptr_t pagenum,
-                                         struct stm_commit_log_entry_s *from,
-                                         struct stm_commit_log_entry_s *to)
+static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum)
 {
-    /* walk the commit log and update the page 'pagenum' until we reach
-       the same revision as our segment, or we reach the HEAD. */
+    /* looks at all bk copies of objects overlapping page 'pagenum' and
+       copies the part in 'pagenum' back to the current segment */
+    dprintf(("copy_bk_objs_in_page_from(%d, %lu)\n", from_segnum, pagenum));
+
+    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);
+
+    _copy_from_undo_log(pagenum, undo, end);
+}
+
+static void go_to_the_future(uintptr_t pagenum,
+                             struct stm_commit_log_entry_s *from,
+                             struct stm_commit_log_entry_s *to)
+{
+    /* walk FORWARDS the commit log and update the page 'pagenum',
+       initially at revision 'from', until we reach the revision 'to'. */
     assert(all_privatization_locks_acquired());
 
-    volatile struct stm_commit_log_entry_s *cl;
-    cl = (volatile struct stm_commit_log_entry_s *)from;
+    while (from != to) {
+        from = from->next;
 
-    if (from == to)
-        return;
+        struct stm_undo_s *undo = from->written;
+        struct stm_undo_s *end = from->written + from->written_count;
 
-    while ((cl = cl->next)) {
-        if (cl == (void *)-1)
-            return;
+        _copy_from_undo_log(pagenum, undo, end);
+    }
+}
 
-        OPT_ASSERT(cl->segment_num >= 0 && cl->segment_num < NB_SEGMENTS);
+static void go_to_the_past(uintptr_t pagenum,
+                           struct stm_commit_log_entry_s *from,
+                           struct stm_commit_log_entry_s *to)
+{
+    /* walk BACKWARDS the commit log and update the page 'pagenum',
+       initially at revision 'from', until we reach the revision 'to'. */
+    assert(all_privatization_locks_acquired());
 
-        object_t *obj;
-        size_t i = 0;
-        while ((obj = cl->written[i].object)) {
-            abort(); //_update_obj_from(cl->segment_num, obj, pagenum);
+    /* XXXXXXX Recursive algo for now, fix this! */
 
-            i++;
-        };
+    if (from != to) {
+        struct stm_commit_log_entry_s *cl = from->next;
+        go_to_the_past(pagenum, cl, to);
 
-        /* last fully validated entry */
-        if (cl == to)
-            return;
+        struct stm_undo_s *undo = cl->written;
+        struct stm_undo_s *end = cl->written + cl->written_count;
+
+        _copy_from_undo_log(pagenum, undo, end);
     }
 }
 
@@ -96,23 +105,48 @@
     /* this assert should be true for now... */
     assert(shared_ref_count == 1);
 
+    /* acquire this lock, so that we know we should get a view
+       of the page we're about to copy that is consistent with the
+       backup copies in the other thread's 'modified_old_objects'. */
+    acquire_modified_objs_lock(shared_page_holder);
+
     /* make our page private */
     page_privatize_in(STM_SEGMENT->segment_num, pagenum);
     assert(get_page_status_in(my_segnum, pagenum) == PAGE_PRIVATE);
 
-    /* if there were modifications in the page, revert them: */
+    /* if there were modifications in the page, revert them. */
     copy_bk_objs_in_page_from(shared_page_holder, pagenum);
 
-    /* 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();
+    /* we need to go from 'src_version' to 'target_version'.  This
+       might need a walk into the past or the future. */
+    struct stm_commit_log_entry_s *src_version, *target_version, *c1, *c2;
+    src_version = get_priv_segment(shared_page_holder)->last_commit_log_entry;
+    target_version = STM_PSEGMENT->last_commit_log_entry;
 
-    /* in case page is already newer, validate everything now to have a common
-       revision for all pages */
-    //_stm_validate(NULL, true);
+    c1 = src_version;
+    c2 = target_version;
+    while (1) {
+        if (c1 == target_version) {
+            go_to_the_future(pagenum, src_version, target_version);
+            break;
+        }
+        if (c2 == src_version) {
+            go_to_the_past(pagenum, src_version, target_version);
+            break;
+        }
+        c1 = c1->next;
+        if (c1 == (void *)-1 || c1 == NULL) {
+            go_to_the_past(pagenum, src_version, target_version);
+            break;
+        }
+        c2 = c2->next;
+        if (c2 == (void *)-1 || c2 == NULL) {
+            go_to_the_future(pagenum, src_version, target_version);
+            break;
+        }
+    }
+
+    release_modified_objs_lock(shared_page_holder);
 }
 
 static void _signal_handler(int sig, siginfo_t *siginfo, void *context)
@@ -210,6 +244,11 @@
     struct stm_commit_log_entry_s *next_cl;
     /* Don't check this 'cl'. This entry is already checked */
 
+    /* We need this lock to prevent a segfault handler in a different thread
+       from seeing inconsistent data.  It could also be done by carefully
+       ordering things, but later. */
+    acquire_modified_objs_lock(STM_SEGMENT->segment_num);
+
     bool needs_abort = false;
     while ((next_cl = cl->next) != NULL) {
         if (next_cl == (void *)-1) {
@@ -248,9 +287,12 @@
         }
 
         /* last fully validated entry */
+
         STM_PSEGMENT->last_commit_log_entry = cl;
     }
 
+    release_modified_objs_lock(STM_SEGMENT->segment_num);
+
     if (needs_abort) {
         if (free_if_abort != (void *)-1)
             free(free_if_abort);
@@ -316,6 +358,7 @@
 
     acquire_modified_objs_lock(STM_SEGMENT->segment_num);
     list_clear(STM_PSEGMENT->modified_old_objects);
+    STM_PSEGMENT->last_commit_log_entry = new;
     release_modified_objs_lock(STM_SEGMENT->segment_num);
 }
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to