Author: Remi Meier <remi.me...@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); _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit