[pypy-commit] stmgc default: progress

Raemi noreply at buildbot.pypy.org
Fri Sep 5 11:51:59 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1354:b58cd671cb54
Date: 2014-09-05 10:18 +0200
http://bitbucket.org/pypy/stmgc/changeset/b58cd671cb54/

Log:	progress

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -14,19 +14,41 @@
     long i;
     int my_segnum = STM_SEGMENT->segment_num;
 
+    assert(!is_readable_log_page_in(my_segnum, pagenum));
+
+    /* make readable */
+    assert(STM_PSEGMENT->privatization_lock); /* we hold it, nobody
+                                                 will privatize a page,
+                                                 necessary? */
+    pages_set_protection(my_segnum, pagenum, 1, PROT_READ|PROT_WRITE);
+
+    assert(!is_shared_log_page(pagenum));
+
     for (i = 0; i < NB_SEGMENTS; i++) {
         if (i == my_segnum)
             continue;
-        if (!is_readable_page(i, first_page))
+        if (!is_readable_log_page_in(i, pagenum))
             continue;
 
         acquire_privatization_lock(i);
+        assert(is_readable_log_page_in(i, pagenum)); /* still... */
 
         /* copy the content from there to our segment */
-        pagecopy(new_page, get_segment_base(from_segnum) + pagenum * 4096UL);
+        pagecopy((char*)(get_virt_page_of(my_segnum, pagenum) * 4096UL),
+                 (char*)(get_virt_page_of(i, pagenum) * 4096UL));
+
+        /* get valid state from backup copies of written objs in
+           the range of this page: */
+        acquire_modified_objs_lock(i);
+
+        release_modified_objs_lock(i);
 
         release_privatization_lock(i);
+
+        return;
     }
+
+    abort();                    /* didn't find a page to copy from?? */
 }
 
 void _signal_handler(int sig, siginfo_t *siginfo, void *context)
@@ -39,27 +61,17 @@
     }
     /* XXX: should we save 'errno'? */
 
-    /* make PROT_READWRITE again and validate */
+
     int segnum = get_segment_of_linear_address(addr);
     OPT_ASSERT(segnum == STM_SEGMENT->segment_num);
     dprintf(("-> segment: %d\n", segnum));
     char *seg_base = STM_SEGMENT->segment_base;
     uintptr_t pagenum = ((char*)addr - seg_base) / 4096UL;
 
-    /* XXX: missing synchronisation: we may change protection, then
-       another thread changes it back, then we try to privatize that
-       calls page_copy() and traps */
-    /* XXX: mprotect is not reentrant and interruptible by signals,
-       so it needs additional synchronisation.*/
-    pages_set_protection(segnum, pagenum, 1, PROT_READ|PROT_WRITE);
+    acquire_privatization_lock(segnum);
+    bring_page_up_to_date(pagenum);
+    release_privatization_lock(segnum);
 
-    bring_page_up_to_date(pagenum);
-
-    /* XXX: ... what can go wrong when we abort from inside
-       the signal handler? */
-
-    /* make sure we are up to date in this (and all other) pages */
-    stm_validate(NULL);
     return;
 }
 
@@ -167,43 +179,40 @@
 
 void _privatize_and_protect_other_segments(object_t *obj)
 {
-    assert(STM_PSEGMENT->privatization_lock); /* we hold it */
-    assert(obj_size < 4096); /* too lazy right now (part of the code is ready) */
+#ifndef NDEBUG
+    long l;
+    for (l = 0; l < NB_SEGMENTS; l++) {
+        assert(get_priv_segment(l)->privatization_lock);
+    }
+#endif
 
     uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
     char *realobj;
     size_t obj_size;
-    uintptr_t i, end_page;
+    uintptr_t i;
     int my_segnum = STM_SEGMENT->segment_num;
 
     realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
-    end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
+    assert(obj_size < 4096); /* XXX */
 
     /* privatize pages: */
-    /* get the last page containing data from the object */
-    end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
-    for (i = first_page; i <= end_page; i++) {
-        if (is_private_page(my_segnum, i))
-            continue;
-        page_privatize(i);
-        bring_page_up_to_date(i);
+    assert(is_shared_log_page(first_page));
+    /* XXX: change this logic:
+       right now, privatization means private in seg0 and private
+       in my_segnum */
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        assert(!is_private_log_page_in(i, first_page));
+
+        if (i != my_segnum && i != 0)
+            pages_set_protection(i, first_page, 1, PROT_NONE);
     }
 
-    /* then PROT_NONE everyone else that doesn't have a private
-       page already */
-    for (i = 0; i < NB_SEGMENTS; i++) {
-        if (i == my_segnum)
-            continue;
-        if (!is_readable_page(i, first_page) || is_private_page(i, first_page))
-            continue;
-
-        acquire_privatization_lock(i);
-        pages_set_protection(i, first_page, end_page - first_page + 1,
-                             PROT_NONE);
-        release_privatization_lock(i);
-
-        dprintf(("prot %lu, len=%lu in seg %lu\n", first_page, (end_page - first_page + 1), i));
+    /* remap pages for my_segnum and copy the contents */
+    if (i != 0) {
+        page_privatize(first_page);
+        pagecopy((char*)(get_virt_page_of(my_segnum, first_page) * 4096UL),
+                 (char*)(get_virt_page_of(0, first_page) * 4096UL));
     }
 }
 
@@ -230,21 +239,28 @@
 
     assert(obj_size < 4096); /* too lazy right now (part of the code is ready) */
 
- retry:
+    if (is_shared_log_page(first_page)) {
+        /* acquire all privatization locks, make private and
+           read protect others */
+        long i;
+        for (i = 0; i < NB_SEGMENTS; i++) {
+            acquire_privatization_lock(i);
+        }
+        if (is_shared_log_page(first_page))
+            _privatize_and_protect_other_segments(obj);
+        for (i = NB_SEGMENTS-1; i >= 0; i--) {
+            release_privatization_lock(i);
+        }
+    }
+    /* page not shared anymore. but we still may have
+       only a read protected page ourselves: */
+
     acquire_privatization_lock(my_segnum);
-    if (!is_readable_page(my_segnum, first_page)) {
-        release_privatization_lock(my_segnum);
+    if (!is_readable_log_page_in(my_segnum, first_page))
+        bring_page_up_to_date(first_page);
+    /* page is not PROT_NONE for us */
 
-        bring_page_up_to_date(first_page);
-
-        spin_loop();
-        goto retry;
-    }
-    /* page is not PROT_NONE for us, we can PROT_NONE all others */
-    _privatize_and_protect_other_segments(obj);
-
-    /* remove the WRITE_BARRIER flag (could be done later, but I
-       think we find more bugs this way) */
+    /* remove the WRITE_BARRIER flag */
     obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
 
     /* done fiddling with protection and privatization */
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -45,14 +45,28 @@
 static void pages_set_protection(int segnum, uintptr_t pagenum,
                                  uintptr_t count, int prot);
 
-static inline bool is_private_page(long segnum, uintptr_t pagenum)
+
+static inline uintptr_t get_virt_page_of(long segnum, uintptr_t pagenum)
+{
+    /* logical page -> virtual page */
+    return (uintptr_t)get_segment_base(segnum) / 4096UL + pagenum;
+}
+
+static inline bool is_shared_log_page(uintptr_t pagenum)
+{
+    assert(pagenum >= PAGE_FLAG_START);
+    return pages_privatized[pagenum - PAGE_FLAG_START].by_segment == 0;
+}
+
+
+static inline bool is_private_log_page_in(long segnum, uintptr_t pagenum)
 {
     assert(pagenum >= PAGE_FLAG_START);
     uint64_t bitmask = 1UL << segnum;
     return (pages_privatized[pagenum - PAGE_FLAG_START].by_segment & bitmask);
 }
 
-static inline bool is_readable_page(long segnum, uintptr_t pagenum)
+static inline bool is_readable_log_page_in(long segnum, uintptr_t pagenum)
 {
     assert(pagenum >= PAGE_FLAG_START);
     uint64_t bitmask = 1UL << segnum;


More information about the pypy-commit mailing list