Author: Armin Rigo <[email protected]>
Branch: c8-new-page-handling
Changeset: r1419:2421dce57e02
Date: 2014-09-24 11:34 +0200
http://bitbucket.org/pypy/stmgc/changeset/2421dce57e02/

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
@@ -3,23 +3,48 @@
 #endif
 
 
-/* ############# signal handler ############# */
+/* General helper: copies objects into our own segment, from some
+   source described by a range of 'struct stm_undo_s'.  Maybe later
+   we could specialize this function to avoid the checks in the
+   inner loop.
+*/
+static void import_objects(
+        int from_segnum,            /* or -1: from undo->backup */
+        uintptr_t pagenum,          /* or -1: "all accessible" */
+        struct stm_undo_s *undo,
+        struct stm_undo_s *end)
+{
+    char *src_segment_base = (from_segnum >= 0 ? get_segment_base(from_segnum)
+                                               : NULL);
 
-static void _copy_from_undo_log(uintptr_t pagenum, struct stm_undo_s *undo,
-                                struct stm_undo_s *end)
-{
     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));
+        if (pagenum == -1) {
+            if (get_page_status_in(STM_SEGMENT->segment_num,
+                                   current_page_num) == PAGE_NO_ACCESS)
+                continue;
         }
+        else {
+            if (current_page_num != pagenum)
+                continue;
+        }
+
+        char *src, *dst;
+        if (src_segment_base != NULL)
+            src = REAL_ADDRESS(src_segment_base, oslice);
+        else
+            src = undo->backup;
+        dst = REAL_ADDRESS(STM_SEGMENT->segment_base, oslice);
+        memcpy(dst, src, SLICE_SIZE(undo->slice));
     }
 }
 
+
+/* ############# signal handler ############# */
+
 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
@@ -30,24 +55,27 @@
     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);
+    import_objects(-1, 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)
 {
+    if (from == to)
+        return;
+    abort();  // XXX I think it's broken, ignoring the other segment's
+              // 'modified_old_objects'; but is that reachable anyway?
+
     /* 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());
-
     while (from != to) {
         from = from->next;
 
         struct stm_undo_s *undo = from->written;
         struct stm_undo_s *end = from->written + from->written_count;
 
-        _copy_from_undo_log(pagenum, undo, end);
+        import_objects(from->segment_num, pagenum, undo, end);
     }
 }
 
@@ -57,10 +85,8 @@
 {
     /* 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());
 
     /* XXXXXXX Recursive algo for now, fix this! */
-
     if (from != to) {
         struct stm_commit_log_entry_s *cl = from->next;
         go_to_the_past(pagenum, cl, to);
@@ -68,7 +94,7 @@
         struct stm_undo_s *undo = cl->written;
         struct stm_undo_s *end = cl->written + cl->written_count;
 
-        _copy_from_undo_log(pagenum, undo, end);
+        import_objects(-1, pagenum, undo, end);
     }
 }
 
@@ -123,6 +149,9 @@
     src_version = get_priv_segment(shared_page_holder)->last_commit_log_entry;
     target_version = STM_PSEGMENT->last_commit_log_entry;
 
+    release_modified_objs_lock(shared_page_holder);
+    release_all_privatization_locks();
+
     c1 = src_version;
     c2 = target_version;
     while (1) {
@@ -145,9 +174,6 @@
             break;
         }
     }
-
-    release_modified_objs_lock(shared_page_holder);
-    release_all_privatization_locks();
 }
 
 static void _signal_handler(int sig, siginfo_t *siginfo, void *context)
@@ -211,32 +237,6 @@
     }
 }
 
-static void reapply_undo_log(struct stm_undo_s *undo)
-{
-    /* read the object (or object slice) described by 'undo', and
-       re-applies it to our current segment.
-    */
-    dprintf(("_update_obj_from_undo(obj=%p, size=%d, ofs=%lu)\n",
-             undo->object, SLICE_SIZE(undo->slice), 
SLICE_OFFSET(undo->slice)));
-
-    size_t ofs = SLICE_OFFSET(undo->slice);
-    size_t size = SLICE_SIZE(undo->slice);
-    stm_char *slice_start = ((stm_char *)undo->object) + ofs;
-    stm_char *slice_end = slice_start + size;
-
-    uintptr_t page_start = ((uintptr_t)slice_start) / 4096;
-    assert((uintptr_t)slice_end <= (page_start + 1) * 4096);
-
-    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 */
-    }
-
-    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 */
 
 static void _stm_validate(void *free_if_abort)
@@ -255,6 +255,7 @@
     acquire_modified_objs_lock(STM_SEGMENT->segment_num);
 
     bool needs_abort = false;
+    uint64_t segment_copied_from = 0;
     while ((next_cl = cl->next) != NULL) {
         if (next_cl == (void *)-1) {
             /* there is an inevitable transaction running */
@@ -263,7 +264,10 @@
                 free(free_if_abort);
             stm_abort_transaction();
 #endif
-            abort();  /* XXX non-busy wait here */
+            abort();  /* XXX non-busy wait here
+                         or: XXX do we always need to wait?  we should just
+                         break out of this loop and let the caller handle it
+                         if it wants to */
             _stm_collectable_safe_point();
             acquire_all_privatization_locks();
             continue;
@@ -273,27 +277,31 @@
         /*int srcsegnum = cl->segment_num;
           OPT_ASSERT(srcsegnum >= 0 && srcsegnum < NB_SEGMENTS);*/
 
-        struct stm_undo_s *undo = cl->written;
-        struct stm_undo_s *end = cl->written + cl->written_count;
-
-        for (; undo < end; undo++) {
-
-            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. */
-                if (!needs_abort) {
+        if (!needs_abort) {
+            struct stm_undo_s *undo = cl->written;
+            struct stm_undo_s *end = cl->written + cl->written_count;
+            for (; undo < end; undo++) {
+                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.
+                    */
                     release_modified_objs_lock(STM_SEGMENT->segment_num);
                     
reset_modified_from_backup_copies(STM_SEGMENT->segment_num);
                     acquire_modified_objs_lock(STM_SEGMENT->segment_num);
                     needs_abort = true;
+                    break;
                 }
             }
-            /* XXXX Here I'm doing something wrong -- arigo */
-            reapply_undo_log(undo);
         }
 
+        struct stm_undo_s *undo = cl->written;
+        struct stm_undo_s *end = cl->written + cl->written_count;
+
+        segment_copied_from |= (1UL << cl->segment_num);
+        import_objects(cl->segment_num, -1, undo, end);
+
         /* last fully validated entry */
 
         STM_PSEGMENT->last_commit_log_entry = cl;
@@ -301,6 +309,15 @@
 
     release_modified_objs_lock(STM_SEGMENT->segment_num);
 
+    /* XXXXXXXXXXXXXXXX CORRECT LOCKING NEEDED XXXXXXXXXXXXXXXXXXXXXX */
+    int segnum;
+    for (segnum = 0; segment_copied_from != 0; segnum++) {
+        if (segment_copied_from & (1UL << segnum)) {
+            segment_copied_from &= ~(1UL << segnum);
+            copy_bk_objs_in_page_from(segnum, -1);
+        }
+    }
+
     if (needs_abort) {
         if (free_if_abort != (void *)-1)
             free(free_if_abort);
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to