[pypy-commit] stmgc default: start with some signal handling

Raemi noreply at buildbot.pypy.org
Wed Sep 3 16:44:20 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1342:d02e51a1b9e1
Date: 2014-09-03 16:45 +0200
http://bitbucket.org/pypy/stmgc/changeset/d02e51a1b9e1/

Log:	start with some signal handling

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -2,9 +2,23 @@
 # error "must be compiled via stmgc.c"
 #endif
 
+#include <signal.h>
+
+
+/* ############# signal handler ############# */
+
+void _signal_handler(int sig, siginfo_t *siginfo, void *context)
+{
+
+    if (siginfo->si_addr == NULL) {
+        /* send to GDB */
+        kill(getpid(), SIGINT);
+    }
+}
 
 /* ############# commit log ############# */
 
+
 void _dbg_print_commit_log()
 {
     struct stm_commit_log_entry_s *cl = &commit_log_root;
@@ -90,6 +104,26 @@
 
     stm_read(obj);
 
+    /* make other segments trap if accessing this object */
+    uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
+    char *realobj;
+    size_t obj_size;
+    uintptr_t i, end_page;
+
+    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;
+
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        if (i == STM_SEGMENT->segment_num)
+            continue;
+
+        char *segment_base = get_segment_base(i);
+        mprotect(segment_base + first_page * 4096,
+                 (end_page - first_page + 1) * 4096, PROT_NONE);
+        dprintf(("prot %lu, len=%lu in seg %d\n", first_page, (end_page - first_page + 1), i));
+    }
+
     LIST_APPEND(STM_PSEGMENT->modified_old_objects, obj);
 
     LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
@@ -162,66 +196,6 @@
 
 /************************************************************/
 
-static void _page_wise_synchronize_object_now(object_t *obj)
-{
-    uintptr_t start = (uintptr_t)obj;
-    uintptr_t first_page = start / 4096UL;
-
-    char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
-    ssize_t obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
-    assert(obj_size >= 16);
-    uintptr_t end = start + obj_size;
-    uintptr_t last_page = (end - 1) / 4096UL;
-    long i, myself = STM_SEGMENT->segment_num;
-
-    for (; first_page <= last_page; first_page++) {
-
-        uintptr_t copy_size;
-        if (first_page == last_page) {
-            /* this is the final fragment */
-            copy_size = end - start;
-        }
-        else {
-            /* this is a non-final fragment, going up to the
-               page's end */
-            copy_size = 4096 - (start & 4095);
-        }
-        /* double-check that the result fits in one page */
-        assert(copy_size > 0);
-        assert(copy_size + (start & 4095) <= 4096);
-
-        char *dst, *src;
-        src = REAL_ADDRESS(STM_SEGMENT->segment_base, start);
-        for (i = 0; i < NB_SEGMENTS; i++) {
-            if (i == myself)
-                continue;
-
-            dst = REAL_ADDRESS(get_segment_base(i), start);
-            if (is_private_page(i, first_page)) {
-                /* The page is a private page.  We need to diffuse this
-                   fragment of object from the shared page to this private
-                   page. */
-                if (copy_size == 4096)
-                    pagecopy(dst, src);
-                else
-                    memcpy(dst, src, copy_size);
-            }
-            else {
-                assert(!memcmp(dst, src, copy_size));  /* same page */
-            }
-        }
-
-        start = (start + 4096) & ~4095;
-    }
-}
-
-void _push_obj_to_other_segments(object_t *obj)
-{
-    acquire_privatization_lock();
-    _page_wise_synchronize_object_now(obj);
-    release_privatization_lock();
-}
-
 static void _finish_transaction()
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -20,7 +20,7 @@
 #define MAP_PAGES_FLAGS     (MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE)
 #define NB_NURSERY_PAGES    (STM_GC_NURSERY/4)
 
-#define TOTAL_MEMORY          (NB_PAGES * 4096UL * (1 + NB_SEGMENTS))
+#define TOTAL_MEMORY          (NB_PAGES * 4096UL * NB_SEGMENTS)
 #define READMARKER_END        ((NB_PAGES * 4096UL) >> 4)
 #define FIRST_OBJECT_PAGE     ((READMARKER_END + 4095) / 4096UL)
 #define FIRST_NURSERY_PAGE    FIRST_OBJECT_PAGE
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,7 @@
 
 static void setup_N_pages(char *pages_addr, uint64_t num)
 {
-    pages_initialize_private((pages_addr - stm_object_pages) / 4096UL, num);
+    pages_initialize_shared((pages_addr - stm_object_pages) / 4096UL, num);
 }
 
 
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -139,9 +139,6 @@
 
         _collect_now(obj);
 
-        /* XXX: only if commit now and only for big objs */
-        _push_obj_to_other_segments(obj);
-
         /* the list could have moved while appending */
         lst = STM_PSEGMENT->objects_pointing_to_nursery;
     }
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -16,31 +16,55 @@
 
 /************************************************************/
 
+static void d_remap_file_pages(char *addr, size_t size, ssize_t pgoff)
+{
+    dprintf(("remap_file_pages: 0x%lx bytes: (seg%ld %p) --> (seg%ld %p)\n",
+             (long)size,
+             (long)((addr - stm_object_pages) / 4096UL) / NB_PAGES,
+             (void *)((addr - stm_object_pages) % (4096UL * NB_PAGES)),
+             (long)pgoff / NB_PAGES,
+             (void *)((pgoff % NB_PAGES) * 4096UL)));
+    assert(size % 4096 == 0);
+    assert(size <= TOTAL_MEMORY);
+    assert(((uintptr_t)addr) % 4096 == 0);
+    assert(addr >= stm_object_pages);
+    assert(addr <= stm_object_pages + TOTAL_MEMORY - size);
+    assert(pgoff >= 0);
+    assert(pgoff <= (TOTAL_MEMORY - size) / 4096UL);
 
-static void pages_initialize_private(uintptr_t pagenum, uintptr_t count)
+    /* 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);
+
+#ifdef USE_REMAP_FILE_PAGES
+    int res = remap_file_pages(addr, size, 0, pgoff, 0);
+    if (UNLIKELY(res < 0))
+        stm_fatalerror("remap_file_pages: %m");
+#else
+    char *res = mmap(addr, size,
+                     PROT_READ | PROT_WRITE,
+                     (MAP_PAGES_FLAGS & ~MAP_ANONYMOUS) | MAP_FIXED,
+                     stm_object_pages_fd, pgoff * 4096UL);
+    if (UNLIKELY(res != addr))
+        stm_fatalerror("mmap (remapping page): %m");
+#endif
+}
+
+
+static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count)
 {
-    dprintf(("pages_initialize_private: 0x%ld - 0x%ld\n", pagenum,
+    /* 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. */
+    dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum,
              pagenum + count));
     assert(pagenum < NB_PAGES);
     if (count == 0)
         return;
-
-    long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
-        spinlock_acquire(get_priv_segment(i)->privatization_lock);
-    }
-
-    while (count-->0) {
-        for (i = 0; i < NB_SEGMENTS; i++) {
-             uint64_t bitmask = 1UL << i;
-             volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
-                 &pages_privatized[pagenum + count - PAGE_FLAG_START];
-
-             ps->by_segment |= bitmask;
-        }
-    }
-
-    for (i = NB_SEGMENTS-1; i >= 0; i--) {
-        spinlock_release(get_priv_segment(i)->privatization_lock);
+    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);
     }
 }
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -20,8 +20,7 @@
 
 static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
 
-static void pages_initialize_private(uintptr_t pagenum, uintptr_t count);
-
+static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
 
 static inline bool is_private_page(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
@@ -2,6 +2,7 @@
 # error "must be compiled via stmgc.c"
 #endif
 
+#include <signal.h>
 
 #ifdef USE_REMAP_FILE_PAGES
 static char *setup_mmap(char *reason, int *ignored)
@@ -67,9 +68,32 @@
             mprotect(segment_base + 8192,
                      (FIRST_READMARKER_PAGE - 2) * 4096UL,
                      PROT_NONE);
+
+        if (i != 0) {
+            /* let's give all pages to segment 0 at first and make them
+               write-inaccessible everywhere else */
+            mprotect(segment_base + END_NURSERY_PAGE * 4096,
+                     (NB_PAGES - END_NURSERY_PAGE) * 4096,
+                     PROT_READ);
+        }
     }
 }
 
+static void setup_signal_handler(void)
+{
+    struct sigaction act;
+    memset(&act, 0, sizeof(act));
+
+	act.sa_sigaction = &_signal_handler;
+	/* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
+	act.sa_flags = SA_SIGINFO;
+
+	if (sigaction(SIGSEGV, &act, NULL) < 0) {
+		perror ("sigaction");
+		abort();
+	}
+}
+
 void stm_setup(void)
 {
     /* Check that some values are acceptable */
@@ -89,6 +113,7 @@
     stm_object_pages = setup_mmap("initial stm_object_pages mmap()",
                                   &stm_object_pages_fd);
     setup_protection_settings();
+    setup_signal_handler();
 
     long i;
     for (i = 0; i < NB_SEGMENTS; i++) {
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -46,7 +46,6 @@
 char *_stm_get_segment_base(long index);
 bool _stm_in_transaction(stm_thread_local_t *tl);
 int _stm_get_flags(object_t *obj);
-void _push_obj_to_other_segments(object_t *obj);
 
 object_t *_stm_allocate_old(ssize_t size_rounded_up);
 long stm_can_move(object_t *obj);
@@ -244,14 +243,12 @@
     o = lib._stm_allocate_old(size)
     tid = 42 + size
     lib._set_type_id(o, tid)
-    lib._push_obj_to_other_segments(o)
     return o
 
 def stm_allocate_old_refs(n):
     o = lib._stm_allocate_old(HDR + n * WORD)
     tid = 421420 + n
     lib._set_type_id(o, tid)
-    lib._push_obj_to_other_segments(o)
     return o
 
 def stm_allocate(size):


More information about the pypy-commit mailing list