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

Raemi noreply at buildbot.pypy.org
Thu Sep 18 16:54:19 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: c8-new-page-handling
Changeset: r1392:5e2059e06b18
Date: 2014-09-18 16:54 +0200
http://bitbucket.org/pypy/stmgc/changeset/5e2059e06b18/

Log:	some progress

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -39,9 +39,8 @@
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     uintptr_t pagenum = (uintptr_t)obj / 4096UL;
 
-    OPT_ASSERT(!is_shared_log_page(pagenum));
-    assert(is_private_log_page_in(STM_SEGMENT->segment_num, pagenum));
-    assert(is_private_log_page_in(from_seg, pagenum));
+    assert(get_page_status_in(from_seg, pagenum) != PAGE_NO_ACCESS);
+    assert(get_page_status_in(STM_SEGMENT->segment_num, pagenum) != PAGE_NO_ACCESS);
 
     /* look the obj up in the other segment's modified_old_objects to
        get its backup copy: */
@@ -218,18 +217,17 @@
     uintptr_t i;
     int my_segnum = STM_SEGMENT->segment_num;
 
-    assert(is_shared_log_page(pagenum));
-    char *src = (char*)(get_virt_page_of(0, pagenum) * 4096UL);
+    XXX();
+    //assert(is_shared_log_page(pagenum));
+    /* char *src = (char*)(get_virt_page_of(0, pagenum) * 4096UL); */
 
-    for (i = 1; i < NB_SEGMENTS; i++) {
-        assert(!is_private_log_page_in(i, pagenum));
+    /* for (i = 1; i < NB_SEGMENTS; i++) { */
+    /*     page_privatize_in(i, pagenum, src); */
+    /* } */
+    /* set_page_private_in(0, pagenum); */
 
-        page_privatize_in(i, pagenum, src);
-    }
-    set_page_private_in(0, pagenum);
-
-    OPT_ASSERT(is_private_log_page_in(my_segnum, pagenum));
-    assert(!is_shared_log_page(pagenum));
+    /* OPT_ASSERT(is_private_log_page_in(my_segnum, pagenum)); */
+    /* assert(!is_shared_log_page(pagenum)); */
 }
 
 void _stm_write_slowpath(object_t *obj)
@@ -259,23 +257,23 @@
 
     uintptr_t page;
     for (page = first_page; page <= end_page; page++) {
-        if (is_shared_log_page(page)) {
-            long i;
-            for (i = 0; i < NB_SEGMENTS; i++) {
-                acquire_privatization_lock(i);
-            }
-            if (is_shared_log_page(page))
-                _privatize_shared_page(page);
-            for (i = NB_SEGMENTS-1; i >= 0; i--) {
-                release_privatization_lock(i);
-            }
-        }
+        XXX();
+        /* if (is_shared_log_page(page)) { */
+        /*     long i; */
+        /*     for (i = 0; i < NB_SEGMENTS; i++) { */
+        /*         acquire_privatization_lock(i); */
+        /*     } */
+        /*     if (is_shared_log_page(page)) */
+        /*         _privatize_shared_page(page); */
+        /*     for (i = NB_SEGMENTS-1; i >= 0; i--) { */
+        /*         release_privatization_lock(i); */
+        /*     } */
+        /* } */
     }
     /* pages not shared anymore. but we still may have
        only a read protected page ourselves: */
 
     acquire_privatization_lock(my_segnum);
-    OPT_ASSERT(is_private_log_page_in(my_segnum, first_page));
 
     /* remove the WRITE_BARRIER flag */
     obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -19,7 +19,8 @@
     for (i = 0; i < NB_SEGMENTS; i++) {
         acquire_privatization_lock(i);
     }
-    pages_initialize_shared((pages_addr - stm_object_pages) / 4096UL, num);
+    pages_initialize_shared_for(STM_SEGMENT->segment_num,
+                                (pages_addr - stm_object_pages) / 4096UL, num);
     for (i = NB_SEGMENTS-1; i >= 0; i--) {
         release_privatization_lock(i);
     }
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -11,12 +11,11 @@
 
 static void teardown_pages(void)
 {
-    memset(pages_privatized, 0, sizeof(pages_privatized));
+    memset(pages_status, 0, sizeof(pages_status));
 }
 
 /************************************************************/
-
-static void d_remap_file_pages(char *addr, size_t size, ssize_t pgoff)
+static void check_remap_makes_sense(char *addr, size_t size, ssize_t pgoff)
 {
     dprintf(("remap_file_pages: 0x%lx bytes: (seg%ld %p) --> (seg%ld %p)\n",
              (long)size,
@@ -35,21 +34,26 @@
     /* assert remappings follow the rule that page N in one segment
        can only be remapped to page N in another segment */
     assert(((addr - stm_object_pages) / 4096UL - pgoff) % NB_PAGES == 0);
+}
+
+static void d_remap_file_pages(char *addr, size_t size, ssize_t pgoff)
+{
+    check_remap_makes_sense(addr, size, pgoff);
 
     char *res = mmap(addr, size,
                      PROT_READ | PROT_WRITE,
-                     (MAP_PAGES_FLAGS & ~MAP_ANONYMOUS) | MAP_FIXED,
+                     MAP_PRIVATE | MAP_NORESERVE | MAP_FIXED,
                      stm_object_pages_fd, pgoff * 4096UL);
     if (UNLIKELY(res != addr))
         stm_fatalerror("mmap (remapping page): %m");
 }
 
 
-static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count)
+static void pages_initialize_shared_for(long segnum, uintptr_t pagenum, uintptr_t count)
 {
     /* call remap_file_pages() to make all pages in the range(pagenum,
-       pagenum+count) refer to the same physical range of pages from
-       segment 0. */
+       pagenum+count) PAGE_SHARED in segnum, and PAGE_NO_ACCESS in other segments */
+
     dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum,
              pagenum + count));
 #ifndef NDEBUG
@@ -61,62 +65,63 @@
     assert(pagenum < NB_PAGES);
     if (count == 0)
         return;
+
+    /* already shared after setup.c (also for the other count-1 pages) */
+    assert(get_page_status_in(segnum, pagenum) == PAGE_SHARED);
+
+    /* make other segments NO_ACCESS: */
     uintptr_t i;
-    for (i = 1; i < NB_SEGMENTS; i++) {
-        char *segment_base = get_segment_base(i);
-        d_remap_file_pages(segment_base + pagenum * 4096UL,
-                           count * 4096UL, pagenum);
-    }
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        if (i != segnum) {
+            char *segment_base = get_segment_base(i);
+            mprotect(segment_base + pagenum * 4096UL,
+                     count * 4096UL, PROT_NONE);
+        }
 
-    for (i = 0; i < NB_SEGMENTS; i++) {
-        uintptr_t amount = count;
-        while (amount-->0) {
-            volatile struct page_shared_s *ps2 = (volatile struct page_shared_s *)
-                &pages_privatized[pagenum + amount - PAGE_FLAG_START];
-
-            ps2->by_segment = 0; /* not private */
-        }
+        long amount = count;
+        while (amount-->0)
+            set_page_status_in(i, pagenum + amount, PAGE_NO_ACCESS);
     }
 }
 
 
-static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from)
-{
-#ifndef NDEBUG
-    long l;
-    for (l = 0; l < NB_SEGMENTS; l++) {
-        assert(get_priv_segment(l)->privatization_lock);
-    }
-#endif
+/* static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from) */
+/* { */
+/* #ifndef NDEBUG */
+/*     long l; */
+/*     for (l = 0; l < NB_SEGMENTS; l++) { */
+/*         assert(get_priv_segment(l)->privatization_lock); */
+/*     } */
+/* #endif */
 
-    /* check this thread's 'pages_privatized' bit */
-    uint64_t bitmask = 1UL << segnum;
-    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
-        &pages_privatized[pagenum - PAGE_FLAG_START];
-    if (ps->by_segment & bitmask) {
-        /* the page is already privatized; nothing to do */
-        return;
-    }
+/*     /\* check this thread's 'pages_privatized' bit *\/ */
+/*     uint64_t bitmask = 1UL << segnum; */
+/*     volatile struct page_shared_s *ps = (volatile struct page_shared_s *) */
+/*         &pages_privatized[pagenum - PAGE_FLAG_START]; */
+/*     if (ps->by_segment & bitmask) { */
+/*         /\* the page is already privatized; nothing to do *\/ */
+/*         return; */
+/*     } */
 
-    dprintf(("page_privatize(%lu) in seg:%d\n", pagenum, segnum));
+/*     dprintf(("page_privatize(%lu) in seg:%d\n", pagenum, segnum)); */
 
-    /* add this thread's 'pages_privatized' bit */
-    ps->by_segment |= bitmask;
+/*     /\* add this thread's 'pages_privatized' bit *\/ */
+/*     ps->by_segment |= bitmask; */
 
-    /* "unmaps" the page to make the address space location correspond
-       again to its underlying file offset (XXX later we should again
-       attempt to group together many calls to d_remap_file_pages() in
-       succession) */
-    uintptr_t pagenum_in_file = NB_PAGES * segnum + pagenum;
-    char *new_page = stm_object_pages + pagenum_in_file * 4096UL;
+/*     /\* "unmaps" the page to make the address space location correspond */
+/*        again to its underlying file offset (XXX later we should again */
+/*        attempt to group together many calls to d_remap_file_pages() in */
+/*        succession) *\/ */
+/*     uintptr_t pagenum_in_file = NB_PAGES * segnum + pagenum; */
+/*     char *new_page = stm_object_pages + pagenum_in_file * 4096UL; */
 
-    /* first write to the file page directly: */
-    ssize_t written = pwrite(stm_object_pages_fd, initialize_from, 4096UL,
-                             pagenum_in_file * 4096UL);
-    if (written != 4096)
-        stm_fatalerror("pwrite didn't write the whole page: %zd", written);
+/*     /\* first write to the file page directly: *\/ */
+/*     ssize_t written = pwrite(stm_object_pages_fd, initialize_from, 4096UL, */
+/*                              pagenum_in_file * 4096UL); */
+/*     if (written != 4096) */
+/*         stm_fatalerror("pwrite didn't write the whole page: %zd", written); */
 
-    /* now remap virtual page in segment to the new file page */
-    write_fence();
-    d_remap_file_pages(new_page, 4096, pagenum_in_file);
-}
+/*     /\* now remap virtual page in segment to the new file page *\/ */
+/*     write_fence(); */
+/*     d_remap_file_pages(new_page, 4096, pagenum_in_file); */
+/* } */
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -20,51 +20,61 @@
 
 #define PAGE_FLAG_START   END_NURSERY_PAGE
 #define PAGE_FLAG_END     NB_PAGES
+/* == NB_SHARED_PAGES */
 
 
 struct page_shared_s {
-#if NB_SEGMENTS <= 8
+#if NB_SEGMENTS <= 4
     uint8_t by_segment;
+#elif NB_SEGMENTS <= 8
+    uint16_t by_segment;
 #elif NB_SEGMENTS <= 16
-    uint16_t by_segment;
+    uint32_t by_segment;
 #elif NB_SEGMENTS <= 32
-    uint32_t by_segment;
-#elif NB_SEGMENTS <= 64
     uint64_t by_segment;
 #else
-#   error "NB_SEGMENTS > 64 not supported right now"
+#   error "NB_SEGMENTS > 32 not supported right now"
 #endif
 };
 
-static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
+enum {
+    PAGE_SHARED = 0,
+    PAGE_PRIVATE,
+    PAGE_NO_ACCESS,
+};
 
-static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
-static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from);
+static struct page_shared_s pages_status[NB_SHARED_PAGES];
+
+static void pages_initialize_shared_for(long segnum, uintptr_t pagenum, uintptr_t count);
+/* static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from); */
+
+
+static inline uint8_t get_page_status_in(long segnum, uintptr_t pagenum)
+{
+    int seg_shift = segnum * 2;
+    uint64_t bitmask = 3UL << seg_shift;
+    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+        &pages_status[pagenum - PAGE_FLAG_START];
+
+    return ((ps->by_segment & bitmask) >> seg_shift) & 3;
+}
+
+static inline void set_page_status_in(long segnum, uintptr_t pagenum, uint8_t status)
+{
+    OPT_ASSERT((status & 3) == status);
+
+    int seg_shift = segnum * 2;
+    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+        &pages_status[pagenum - PAGE_FLAG_START];
+
+    assert(status != get_page_status_in(segnum, pagenum));
+    ps->by_segment |= status << seg_shift;
+}
+
+
 
 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 void set_page_private_in(long segnum, uintptr_t pagenum)
-{
-    uint64_t bitmask = 1UL << segnum;
-    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
-        &pages_privatized[pagenum - PAGE_FLAG_START];
-    assert(!(ps->by_segment & bitmask));
-    ps->by_segment |= bitmask;
-}
-
-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);
-}


More information about the pypy-commit mailing list