[pypy-commit] stmgc default: uhm, try to do atomic privatization of pages

Raemi noreply at buildbot.pypy.org
Wed Sep 10 15:25:35 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1382:777200bdb987
Date: 2014-09-10 15:27 +0200
http://bitbucket.org/pypy/stmgc/changeset/777200bdb987/

Log:	uhm, try to do atomic privatization of pages

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -224,8 +224,7 @@
     for (i = 1; i < NB_SEGMENTS; i++) {
         assert(!is_private_log_page_in(i, pagenum));
 
-        page_privatize_in(i, pagenum);
-        pagecopy((char*)(get_virt_page_of(i, pagenum) * 4096UL), src);
+        page_privatize_in(i, pagenum, src);
     }
     set_page_private_in(0, pagenum);
 
@@ -256,23 +255,23 @@
     struct object_s *bk_obj = malloc(obj_size);
     memcpy(bk_obj, realobj, obj_size);
 
-    if (is_shared_log_page(first_page)) {
-        /* acquire all privatization locks, make private and
-           read protect others */
-        long i;
-        uintptr_t page;
-        for (i = 0; i < NB_SEGMENTS; i++) {
-            acquire_privatization_lock(i);
-        }
-        for (page = first_page; page <= end_page; page++) {
+    /* if there are shared pages, privatize them */
+
+    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);
+            for (i = NB_SEGMENTS-1; i >= 0; i--) {
+                release_privatization_lock(i);
+            }
         }
     }
-    /* page not shared anymore. but we still may have
+    /* pages not shared anymore. but we still may have
        only a read protected page ourselves: */
 
     acquire_privatization_lock(my_segnum);
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -32,6 +32,7 @@
 #define FIRST_OLD_RM_PAGE     (OLD_RM_START / 4096UL)
 #define NB_READMARKER_PAGES   (FIRST_OBJECT_PAGE - FIRST_READMARKER_PAGE)
 
+#define TMP_COPY_PAGE         1 /* HACK */
 
 enum /* stm_flags */ {
     GCFLAG_WRITE_BARRIER = _STM_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
@@ -15,7 +15,14 @@
 
 static void setup_N_pages(char *pages_addr, uint64_t num)
 {
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        acquire_privatization_lock(i);
+    }
     pages_initialize_shared((pages_addr - stm_object_pages) / 4096UL, num);
+    for (i = NB_SEGMENTS-1; i >= 0; i--) {
+        release_privatization_lock(i);
+    }
 }
 
 
@@ -43,7 +50,7 @@
     }
     dprintf(("allocate_outside_nursery_large(%lu): %p, seg=%d, page=%lu\n",
              size, addr, get_segment_of_linear_address(addr),
-             (addr - STM_SEGMENT->segment_base) / 4096UL));
+             (addr - get_segment_base(get_segment_of_linear_address(addr))) / 4096UL));
 
     spinlock_release(lock_growth_large);
     return addr;
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -34,7 +34,8 @@
 
     /* 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);
+    assert(IMPLY(((addr - stm_object_pages) / 4096UL) != TMP_COPY_PAGE,
+                 ((addr - stm_object_pages) / 4096UL - pgoff) % NB_PAGES == 0));
 
 #ifdef USE_REMAP_FILE_PAGES
     int res = remap_file_pages(addr, size, 0, pgoff, 0);
@@ -58,6 +59,12 @@
        segment 0. */
     dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum,
              pagenum + count));
+#ifndef NDEBUG
+    long l;
+    for (l = 0; l < NB_SEGMENTS; l++) {
+        assert(get_priv_segment(l)->privatization_lock);
+    }
+#endif
     assert(pagenum < NB_PAGES);
     if (count == 0)
         return;
@@ -79,10 +86,15 @@
     }
 }
 
-static void page_privatize_in(int segnum, uintptr_t pagenum)
+
+static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from)
 {
-    /* hopefully holding the lock */
-    assert(get_priv_segment(segnum)->privatization_lock);
+#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;
@@ -103,6 +115,14 @@
        attempt to group together many calls to d_remap_file_pages() in
        succession) */
     uintptr_t pagenum_in_file = NB_PAGES * segnum + pagenum;
+    char *tmp_page = stm_object_pages + TMP_COPY_PAGE * 4096UL;
+    /* first remap to TMP_PAGE, then copy stuff there (to the underlying
+       file page), then remap this file-page hopefully atomically to the
+       segnum's virtual page */
+    d_remap_file_pages(tmp_page, 4096, pagenum_in_file);
+    pagecopy(tmp_page, initialize_from);
+    write_fence();
+
     char *new_page = stm_object_pages + pagenum_in_file * 4096UL;
     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
@@ -40,7 +40,7 @@
 static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
 
 static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
-static void page_privatize_in(int segnum, uintptr_t pagenum);
+static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from);
 
 static inline uintptr_t get_virt_page_of(long segnum, uintptr_t pagenum)
 {
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -63,11 +63,19 @@
            NULL accesses land.  We mprotect it so that accesses fail. */
         mprotect(segment_base, 4096, PROT_NONE);
 
+        /* TMP_COPY_PAGE is used for atomic privatization */
+        mprotect(segment_base + TMP_COPY_PAGE * 4096UL,
+                 4096UL, PROT_READ|PROT_WRITE);
+
         /* Pages in range(2, FIRST_READMARKER_PAGE) are never used */
-        if (FIRST_READMARKER_PAGE > 2)
-            mprotect(segment_base + 8192,
-                     (FIRST_READMARKER_PAGE - 2) * 4096UL,
+        if (FIRST_READMARKER_PAGE > TMP_COPY_PAGE + 1)
+            mprotect(segment_base + (TMP_COPY_PAGE + 1) * 4096,
+                     (FIRST_READMARKER_PAGE - TMP_COPY_PAGE - 1) * 4096UL,
                      PROT_NONE);
+
+        /* STM_SEGMENT */
+        mprotect(segment_base + ((uintptr_t)STM_SEGMENT / 4096UL) * 4096UL,
+                 4096UL, PROT_READ|PROT_WRITE);
     }
 }
 
@@ -75,11 +83,13 @@
 void stm_setup(void)
 {
     /* Check that some values are acceptable */
+    assert(TMP_COPY_PAGE > 0 && TMP_COPY_PAGE <= 1);
+    assert(TMP_COPY_PAGE * 4096 + 4096 <= ((uintptr_t)STM_SEGMENT));
+    assert((uintptr_t)STM_SEGMENT == (uintptr_t)STM_PSEGMENT);
+    assert(((uintptr_t)STM_PSEGMENT) + sizeof(*STM_PSEGMENT) <= FIRST_READMARKER_PAGE*4096);
+
     assert(NB_SEGMENTS <= NB_SEGMENTS_MAX);
-    assert(4096 <= ((uintptr_t)STM_SEGMENT));
-    assert((uintptr_t)STM_SEGMENT == (uintptr_t)STM_PSEGMENT);
-    assert(((uintptr_t)STM_PSEGMENT) + sizeof(*STM_PSEGMENT) <= 8192);
-    assert(2 <= FIRST_READMARKER_PAGE);
+    assert(TMP_COPY_PAGE < FIRST_READMARKER_PAGE);
     assert(FIRST_READMARKER_PAGE * 4096UL <= READMARKER_START);
     assert(READMARKER_START < READMARKER_END);
     assert(READMARKER_END <= 4096UL * FIRST_OBJECT_PAGE);
@@ -98,7 +108,7 @@
         char *segment_base = get_segment_base(i);
 
         /* Fill the TLS page (page 1) with 0xDC, for debugging */
-        memset(REAL_ADDRESS(segment_base, 4096), 0xDC, 4096);
+        memset(REAL_ADDRESS(segment_base, ((uintptr_t)STM_PSEGMENT/4096) * 4096), 0xDC, 4096);
         /* Make a "hole" at STM_PSEGMENT (which includes STM_SEGMENT) */
         memset(REAL_ADDRESS(segment_base, STM_PSEGMENT), 0,
                sizeof(*STM_PSEGMENT));
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -34,7 +34,7 @@
     uintptr_t nursery_end;
     struct stm_thread_local_s *running_thread;
 };
-#define STM_SEGMENT           ((stm_segment_info_t *)4352)
+#define STM_SEGMENT           ((stm_segment_info_t *)8192)
 
 
 struct stm_shadowentry_s {


More information about the pypy-commit mailing list