Author: Armin Rigo <[email protected]>
Branch: c8-private-pages
Changeset: r1510:e305d59e0a3d
Date: 2014-12-02 21:07 +0100
http://bitbucket.org/pypy/stmgc/changeset/e305d59e0a3d/

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,20 +3,6 @@
 #endif
 
 
-#ifdef NDEBUG
-#define EVENTUALLY(condition)    {/* nothing */}
-#else
-#define EVENTUALLY(condition)                                   \
-    {                                                           \
-        if (!(condition)) {                                     \
-            acquire_privatization_lock(STM_SEGMENT->segment_num);\
-            if (!(condition))                                   \
-                stm_fatalerror("fails: " #condition);           \
-            release_privatization_lock(STM_SEGMENT->segment_num);\
-        }                                                       \
-    }
-#endif
-
 /* 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
@@ -280,7 +266,7 @@
     dprintf(("_stm_validate(%p)\n", free_if_abort));
     /* go from last known entry in commit log to the
        most current one and apply all changes done
-       by other transactions. Abort if we read one of
+       by other transactions. Abort if we have read one of
        the committed objs. */
     struct stm_commit_log_entry_s *first_cl = 
STM_PSEGMENT->last_commit_log_entry;
     struct stm_commit_log_entry_s *next_cl, *last_cl, *cl;
@@ -346,6 +332,10 @@
 
                 segment_really_copied_from |= (1UL << cl->segment_num);
                 import_objects(cl->segment_num, -1, undo, end);
+
+                copy_bk_objs_in_page_from(
+                    segnum, -1,     /* any page */
+                    !needs_abort);  /* if we abort, we still want to copy 
everything */
             }
 
             /* last fully validated entry */
@@ -355,18 +345,15 @@
         }
         assert(cl == last_cl);
 
-        OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS));
-        int segnum;
-        for (segnum = 0; segnum < NB_SEGMENTS; segnum++) {
-            if (segment_really_copied_from & (1UL << segnum)) {
-                /* here we can actually have our own modified version, so
-                   make sure to only copy things that are not modified in our
-                   segment... (if we do not abort) */
-                copy_bk_objs_in_page_from(
-                    segnum, -1,     /* any page */
-                    !needs_abort);  /* if we abort, we still want to copy 
everything */
-            }
-        }
+        /* OPT_ASSERT(segment_really_copied_from <= ((1UL << NB_SEGMENTS) - 
1)); */
+        /* int segnum; */
+        /* for (segnum = 0; segnum < NB_SEGMENTS; segnum++) { */
+        /*     if (segment_really_copied_from & (1UL << segnum)) { */
+        /*         /\* here we can actually have our own modified version, so 
*/
+        /*            make sure to only copy things that are not modified in 
our */
+        /*            segment... (if we do not abort) *\/ */
+        /*     } */
+        /* } */
     }
 
     /* done with modifications */
@@ -654,7 +641,7 @@
     enter_safe_point_if_requested();
     dprintf(("> start_transaction\n"));
 
-    s_mutex_unlock();
+    s_mutex_unlock();   // XXX it's probably possible to not acquire this here
 
     uint8_t old_rv = STM_SEGMENT->transaction_read_version;
     STM_SEGMENT->transaction_read_version = old_rv + 1;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -73,7 +73,7 @@
     struct tree_s *young_outside_nursery;
     struct tree_s *nursery_objects_shadows;
 
-    uint8_t privatization_lock;
+    uint8_t privatization_lock;  // XXX KILL
 
     uint8_t safe_point;
     uint8_t transaction_state;
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -5,9 +5,8 @@
 
 static void setup_gcpage(void)
 {
-    /* XXXXXXX should use stm_file_pages, no? */
-    uninitialized_page_start = stm_file_pages;
-    uninitialized_page_stop  = stm_file_pages + NB_SHARED_PAGES * 4096UL;
+    //uninitialized_page_start = stm_file_pages;
+    //uninitialized_page_stop  = stm_file_pages + NB_SHARED_PAGES * 4096UL;
 }
 
 static void teardown_gcpage(void)
diff --git a/c8/stm/gcpage.h b/c8/stm/gcpage.h
--- a/c8/stm/gcpage.h
+++ b/c8/stm/gcpage.h
@@ -2,8 +2,8 @@
 /* Granularity when grabbing more unused pages: take 50 at a time */
 #define GCPAGE_NUM_PAGES   50
 
-static char *uninitialized_page_start;   /* within segment 0 */
-static char *uninitialized_page_stop;
+//static char *uninitialized_page_start;   /* within segment 0 */
+//static char *uninitialized_page_stop;
 
 static void setup_gcpage(void);
 static void teardown_gcpage(void);
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -16,71 +16,26 @@
 
 /************************************************************/
 
-static void pages_initialize_shared_for(long segnum, uintptr_t pagenum, 
uintptr_t count)
+
+static void page_mark_accessible(long segnum, uintptr_t pagenum)
 {
-    /* call remap_file_pages() to make all pages in the range(pagenum,
-       pagenum+count) PAGE_SHARED in segnum, and PAGE_NO_ACCESS in other 
segments
-       initialize to |S|N|N|N| */
+    assert(get_page_status_in(segnum, pagenum) == PAGE_NO_ACCESS);
+    dprintf(("page_mark_accessible(%lu) in seg:%ld\n", pagenum, segnum));
 
-    dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum, pagenum + 
count));
+    mprotect(get_virtual_page(segnum, pagenum), 4096, PROT_READ | PROT_WRITE);
 
-    assert(all_privatization_locks_acquired());
-
-    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 = 0; i < NB_SEGMENTS; i++) {
-        if (i != segnum) {
-            char *segment_base = get_segment_base(i);
-            mprotect(segment_base + pagenum * 4096UL,
-                     count * 4096UL, PROT_NONE);
-
-            /* char *result = mmap( */
-            /*     segment_base + pagenum * 4096UL, */
-            /*     count * 4096UL, */
-            /*     PROT_NONE, */
-            /*     MAP_FIXED|MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, */
-            /*     -1, 0); */
-            /* if (result == MAP_FAILED) */
-            /*     stm_fatalerror("pages_initialize_shared failed (mmap): 
%m"); */
-
-
-            long amount = count;
-            while (amount-->0) {
-                set_page_status_in(i, pagenum + amount, PAGE_NO_ACCESS);
-            }
-        }
-    }
+    /* set this flag *after* we un-protected it, because XXX later */
+    set_page_status_in(segnum, pagenum, PAGE_ACCESSIBLE);
 }
 
+static void page_mark_inaccessible(long segnum, uintptr_t pagenum)
+{
+    assert(get_page_status_in(segnum, pagenum) == PAGE_ACCESSIBLE);
+    dprintf(("page_mark_inaccessible(%lu) in seg:%ld\n", pagenum, segnum));
 
-static void page_privatize_in(int segnum, uintptr_t pagenum)
-{
-#ifndef NDEBUG
-    long l;
-    for (l = 0; l < NB_SEGMENTS; l++) {
-        assert(get_priv_segment(l)->privatization_lock);
-    }
-#endif
-    assert(get_page_status_in(segnum, pagenum) == PAGE_NO_ACCESS);
-    dprintf(("page_privatize(%lu) in seg:%d\n", pagenum, segnum));
+    set_page_status_in(segnum, pagenum, PAGE_ACCESSIBLE);
 
-    char *addr = (char*)(get_virt_page_of(segnum, pagenum) * 4096UL);
-    char *result = mmap(
-        addr, 4096UL, PROT_READ | PROT_WRITE,
-        MAP_FIXED | MAP_PRIVATE | MAP_NORESERVE,
-        stm_object_pages_fd, get_file_page_of(pagenum) * 4096UL);
-    if (result == MAP_FAILED)
-        stm_fatalerror("page_privatize_in failed (mmap): %m");
-
-    set_page_status_in(segnum, pagenum, PAGE_PRIVATE);
-
-    volatile char *dummy = REAL_ADDRESS(get_segment_base(segnum), 
pagenum*4096UL);
-    *dummy = *dummy;            /* force copy-on-write from shared page */
+    char *addr = get_virtual_page(segnum, pagenum);
+    madvise(get_virtual_page(segnum, pagenum), 4096, MADV_DONTNEED);
+    mprotect(addr, 4096, PROT_NONE);
 }
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -3,90 +3,61 @@
       logical page
   We have virtual pages: one virtual address can point in some
       virtual page. We have NB_SEGMENTS virtual pages per logical page.
-  We have file pages: they correspond mostly to physical memory pages
-      used for mmap/remap_file_pages
 
-  A logical page is SHARED iff all NB_SEGMENTS virtual pages point to
-  one file page, and thus to the same logical page.
-
-  A logical page becomes PRIVATE if one virtual page still maps to the
-  original file page, and all others turn read protected.
-   -> only one can modify it.
-
-  A logical page can also be "PRIVATE IN A SEGMENT", referring to
-  the virtual page of the segment having its own file page backing.
-  It also implies the logical page is not read protected.
+  Each virtual page is either accessible, or PAGE_NO_ACCESS (and then
+  has no underlying memory).
 */
 
 #define PAGE_FLAG_START   END_NURSERY_PAGE
 #define PAGE_FLAG_END     NB_PAGES
-/* == NB_SHARED_PAGES */
 
 struct page_shared_s {
-#if NB_SEGMENTS <= 4
+#if NB_SEGMENTS <= 8
     uint8_t by_segment;
-#elif NB_SEGMENTS <= 8
+#elif NB_SEGMENTS <= 16
     uint16_t by_segment;
-#elif NB_SEGMENTS <= 16
+#elif NB_SEGMENTS <= 32
     uint32_t by_segment;
-#elif NB_SEGMENTS <= 32
+#elif NB_SEGMENTS <= 64
     uint64_t by_segment;
 #else
-#   error "NB_SEGMENTS > 32 not supported right now"
+#   error "NB_SEGMENTS > 64 not supported right now"
 #endif
 };
 
 enum {
-    PAGE_SHARED = 0,
-    PAGE_PRIVATE = 1,
-    PAGE_NO_ACCESS = 2,
+    PAGE_NO_ACCESS = 0,
+    PAGE_ACCESSIBLE = 1
 };
 
-static struct page_shared_s pages_status[NB_SHARED_PAGES];
+static struct page_shared_s pages_status[PAGE_FLAG_END - PAGE_FLAG_START];
 
-static void pages_initialize_shared_for(long segnum, uintptr_t pagenum, 
uintptr_t count);
-static void page_privatize_in(int segnum, uintptr_t pagenum);
+static void page_mark_accessible(long segnum, uintptr_t pagenum);
+static void page_mark_inaccessible(long segnum, uintptr_t pagenum);
 
 
-
-
-static inline uintptr_t get_virt_page_of(long segnum, uintptr_t pagenum)
+static inline char *get_virtual_page(long segnum, uintptr_t pagenum)
 {
     /* logical page -> virtual page */
-    return (uintptr_t)get_segment_base(segnum) / 4096UL + pagenum;
+    return get_segment_base(segnum) + pagenum * 4096;
 }
 
-static inline uintptr_t get_file_page_of(uintptr_t pagenum)
+static inline bool get_page_status_in(long segnum, uintptr_t pagenum)
 {
-    /* logical page -> file page */
-    return pagenum - PAGE_FLAG_START;
+    OPT_ASSERT(segnum < 8 * sizeof(struct page_shared_s));
+    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+        &pages_status[pagenum - PAGE_FLAG_START];
+
+    return (ps->by_segment >> segnum) & 1;
 }
 
-static inline uintptr_t get_page_of_file_page(uintptr_t file_page)
+static inline void set_page_status_in(long segnum, uintptr_t pagenum,
+                                      bool status)
 {
-    return file_page + END_NURSERY_PAGE;
-}
-
-static inline uint8_t get_page_status_in(long segnum, uintptr_t pagenum)
-{
-    int seg_shift = segnum * 2;
-    OPT_ASSERT(seg_shift < 8 * sizeof(struct page_shared_s));
+    OPT_ASSERT(segnum < 8 * sizeof(struct page_shared_s));
     volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
-        &pages_status[get_file_page_of(pagenum)];
-
-    return (ps->by_segment >> seg_shift) & 3;
-}
-
-static inline void set_page_status_in(long segnum, uintptr_t pagenum, uint8_t 
status)
-{
-    OPT_ASSERT(status < 3);
-
-    int seg_shift = segnum * 2;
-    OPT_ASSERT(seg_shift < 8 * sizeof(struct page_shared_s));
-    volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
-        &pages_status[get_file_page_of(pagenum)];
+        &pages_status[pagenum - PAGE_FLAG_START];
 
     assert(status != get_page_status_in(segnum, pagenum));
-    ps->by_segment &= ~(3UL << seg_shift); /* clear */
-    ps->by_segment |= status << seg_shift; /* set */
+    __sync_fetch_and_xor(&ps->by_segment, 1UL << segnum); /* invert the flag */
 }
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -7,56 +7,14 @@
 
 static void setup_mmap(char *reason)
 {
-    char name[] = "/__stmgc_c8__";
-
-    /* Create the big shared memory object, and immediately unlink it.
-       There is a small window where if this process is killed the
-       object is left around.  It doesn't seem possible to do anything
-       about it...
-    */
-    stm_object_pages_fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
-    shm_unlink(name);
-
-    if (stm_object_pages_fd == -1)
-        stm_fatalerror("%s failed (stm_open): %m", reason);
-
-    if (ftruncate(stm_object_pages_fd, NB_SHARED_PAGES * 4096UL) != 0)
-        stm_fatalerror("%s failed (ftruncate): %m", reason);
-
-    stm_file_pages = mmap(NULL, NB_SHARED_PAGES * 4096UL,
-                          PROT_READ | PROT_WRITE,
-                          MAP_SHARED | MAP_NORESERVE,
-                          stm_object_pages_fd, 0);
-
-    if (stm_file_pages == MAP_FAILED)
-        stm_fatalerror("%s failed (mmap): %m", reason);
-
-
     /* reserve the whole virtual memory space of the program for
-       all segments: */
-    stm_object_pages = mmap(NULL, TOTAL_MEMORY,
-                            PROT_READ | PROT_WRITE,
+       all segments: (for now in one big block, but later could be
+       allocated per-segment) */
+    stm_object_pages = mmap(NULL, TOTAL_MEMORY, PROT_NONE,
                             MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS,
                             -1, 0);
     if (stm_object_pages == MAP_FAILED)
         stm_fatalerror("%s failed (mmap): %m", reason);
-
-    /* remap the shared part of the segments to the file pages */
-    long l;
-    for (l = 0; l < NB_SEGMENTS; l++) {
-        char *result = mmap(
-            stm_object_pages + (l * NB_PAGES + END_NURSERY_PAGE) * 4096UL, /* 
addr */
-            NB_SHARED_PAGES * 4096UL, /* len */
-            PROT_READ | PROT_WRITE,
-            MAP_FIXED | MAP_SHARED | MAP_NORESERVE,
-            stm_object_pages_fd, 0); /* file & offset */
-        if (result == MAP_FAILED)
-            stm_fatalerror("%s failed (mmap): %m", reason);
-    }
-}
-static void close_fd_mmap(int map_fd)
-{
-    close(map_fd);
 }
 
 static void setup_protection_settings(void)
@@ -65,17 +23,13 @@
     for (i = 0; i < NB_SEGMENTS; i++) {
         char *segment_base = get_segment_base(i);
 
-        /* In each segment, the first page is where TLPREFIX'ed
-           NULL accesses land.  We mprotect it so that accesses fail. */
-        mprotect(segment_base, 4096, PROT_NONE);
+        /* In each segment, the second page is where STM_SEGMENT lands. */
+        mprotect(segment_base + 4096, 4096, PROT_READ | PROT_WRITE);
 
-        /* Pages in range(2, FIRST_READMARKER_PAGE) are never used */
-        if (FIRST_READMARKER_PAGE > 2)
-            mprotect(segment_base + 2 * 4096,
-                     (FIRST_READMARKER_PAGE - 2) * 4096UL,
-                     PROT_NONE);
-
-        /* STM_SEGMENT-TL is in page 1 */
+        /* Make the read marker pages accessible, as well as the nursery. */
+        mprotect(segment_base + FIRST_READMARKER_PAGE * 4096,
+                 (NB_READMARKER_PAGES + NB_NURSERY_PAGES) * 4096,
+                 PROT_READ | PROT_WRITE);
     }
 }
 
@@ -184,7 +138,6 @@
     stm_object_pages = NULL;
     commit_log_root.next = NULL; /* xxx:free them */
     commit_log_root.segment_num = -1;
-    close_fd_mmap(stm_object_pages_fd);
 
     teardown_sync();
     teardown_gcpage();
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to