[pypy-commit] stmgc c8-reshare-pages: do a direct NOACCES->ACCESSIBLE if the SIGSEGV is a write operation
Raemi
pypy.commits at gmail.com
Mon Feb 27 11:40:13 EST 2017
Author: Remi Meier <remi.meier at gmail.com>
Branch: c8-reshare-pages
Changeset: r2017:5911d9fa238e
Date: 2017-02-27 17:38 +0100
http://bitbucket.org/pypy/stmgc/changeset/5911d9fa238e/
Log: do a direct NOACCES->ACCESSIBLE if the SIGSEGV is a write operation
Apparently the kernel can tell us if the SIGSEGV is caused by a
write. Then we can avoid the NOACCESS->RO->RW dance, saving ~10% of
SIGSEGV on test_random.
> strace ~/pypy_dir/pytest.py test_zrandom.py -vx -k 10 2>&1 |egrep
"SIGSEGV"|wc -l
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -817,7 +817,7 @@
if (get_page_status_in(my_segnum, page) != PAGE_ACCESSIBLE) {
release_privatization_lock(STM_SEGMENT->segment_num);
/* emulate pagefault -> PAGE_ACCESSIBLE/READONLY: */
- handle_segfault_in_page(page);
+ handle_segfault_in_page(page, false);
volatile char *dummy = REAL_ADDRESS(STM_SEGMENT->segment_base, page * 4096UL);
*dummy = *dummy; /* force segfault (incl. writing) */
acquire_privatization_lock(STM_SEGMENT->segment_num);
diff --git a/c8/stm/signal_handler.c b/c8/stm/signal_handler.c
--- a/c8/stm/signal_handler.c
+++ b/c8/stm/signal_handler.c
@@ -61,8 +61,26 @@
}
+static void readonly_to_accessible(int my_segnum, uintptr_t pagenum)
+{
+ /* make our page write-ready */
+ page_mark_accessible(my_segnum, pagenum);
+
+ /* our READONLY copy *has* to have the current data, no
+ copy necessary */
+ /* make READONLY pages in other segments NO_ACCESS */
+ for (int i = 1; i < NB_SEGMENTS; i++) {
+ if (i == my_segnum)
+ continue;
+
+ if (get_page_status_in(i, pagenum) == PAGE_READONLY)
+ page_mark_inaccessible(i, pagenum);
+ }
+
+}
+
long ro_to_acc = 0;
-static void handle_segfault_in_page(uintptr_t pagenum)
+static void handle_segfault_in_page(uintptr_t pagenum, bool is_write)
{
/* assumes page 'pagenum' is ACCESS_NONE, privatizes it,
and validates to newest revision */
@@ -78,22 +96,13 @@
assert(page_status == PAGE_NO_ACCESS
|| page_status == PAGE_READONLY);
+
+ //is_write=false;
+ if (page_status == PAGE_READONLY || is_write) {
+ dprintf(("SHORTCUT\n"));
+ readonly_to_accessible(my_segnum, pagenum);
+ }
if (page_status == PAGE_READONLY) {
- /* make our page write-ready */
- page_mark_accessible(my_segnum, pagenum);
-
- dprintf((" > found READONLY, make others NO_ACCESS\n"));
- /* our READONLY copy *has* to have the current data, no
- copy necessary */
- /* make READONLY pages in other segments NO_ACCESS */
- for (i = 1; i < NB_SEGMENTS; i++) {
- if (i == my_segnum)
- continue;
-
- if (get_page_status_in(i, pagenum) == PAGE_READONLY)
- page_mark_inaccessible(i, pagenum);
- }
-
ro_to_acc++;
release_all_privatization_locks();
@@ -155,7 +164,8 @@
}
/* make our page write-ready */
- page_mark_accessible(my_segnum, pagenum);
+ if (!is_write) // is_write -> already marked accessible above
+ page_mark_accessible(my_segnum, pagenum);
/* account for this page now: XXX */
/* increment_total_allocated(4096); */
@@ -230,8 +240,11 @@
abort();
}
+ // http://stackoverflow.com/questions/17671869/how-to-identify-read-or-write-operations-of-page-fault-when-using-sigaction-hand
+ bool is_write = ((ucontext_t*)context)->uc_mcontext.gregs[REG_ERR] & 0x2;
+
DEBUG_EXPECT_SEGFAULT(false);
- handle_segfault_in_page(pagenum);
+ handle_segfault_in_page(pagenum, is_write);
DEBUG_EXPECT_SEGFAULT(true);
errno = saved_errno;
diff --git a/c8/stm/signal_handler.h b/c8/stm/signal_handler.h
--- a/c8/stm/signal_handler.h
+++ b/c8/stm/signal_handler.h
@@ -2,7 +2,7 @@
static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum,
bool only_if_not_modified);
-static void handle_segfault_in_page(uintptr_t pagenum);
+static void handle_segfault_in_page(uintptr_t pagenum, bool is_write);
static void setup_signal_handler(void);
More information about the pypy-commit
mailing list