Author: Armin Rigo <ar...@tunes.org> Branch: c7-fork Changeset: r1065:f467a519f7b6 Date: 2014-03-18 10:29 +0100 http://bitbucket.org/pypy/stmgc/changeset/f467a519f7b6/
Log: in-progress, maybe, who knows diff --git a/c7/stm/forksupport.c b/c7/stm/forksupport.c new file mode 100644 --- /dev/null +++ b/c7/stm/forksupport.c @@ -0,0 +1,94 @@ +#ifndef _STM_CORE_H_ +# error "must be compiled via stmgc.c" +#endif + + +/* XXX this is currently not doing copy-on-write, but simply forces a + copy of all shared pages as soon as fork() is called. */ + + +static char *fork_big_copy; + + +static void forksupport_prepare(void) +{ + if (stm_object_pages == NULL) + return; + + /* This silently assumes that fork() is not called from transactions. + It's hard to check though... + */ + s_mutex_lock(); + + synchronize_all_threads(); + + mutex_pages_lock(); + + char *big_copy = setup_mmap("stmgc's fork support"); + + uintptr_t pagenum, endpagenum; + pagenum = END_NURSERY_PAGE; /* starts after the nursery */ + endpagenum = (uninitialized_page_start - stm_object_pages) / 4096UL; + + while (1) { + if (UNLIKELY(pagenum == endpagenum)) { + /* we reach this point usually twice, because there are + more pages after 'uninitialized_page_stop' */ + if (endpagenum == NB_PAGES) + break; /* done */ + pagenum = (uninitialized_page_stop - stm_object_pages) / 4096UL; + endpagenum = NB_PAGES; + if (pagenum == endpagenum) + break; /* no pages in the 2nd section, so done too */ + } + + pagecopy(big_copy + pagenum * 4096UL, + stm_object_pages + pagenum * 4096UL); + pagenum++; + } + + assert(fork_big_copy == NULL); + fork_big_copy = big_copy; +} + +static void forksupport_parent(void) +{ + if (stm_object_pages == NULL) + return; + + assert(fork_big_copy != NULL); + munmap(fork_big_copy, TOTAL_MEMORY); + stm_object_pages = NULL; + + mutex_pages_unlock(); + s_mutex_unlock(); +} + +static void forksupport_child(void) +{ + if (stm_object_pages == NULL) + return; + + mremap(fork_big_copy, TOTAL_MEMORY, TOTAL_MEMORY, + MREMAP_MAYMOVE | MREMAP_FIXED, + stm_object_pages); + + ...; reset carefully a much bigger part of the state here :-((( + memset(pages_privatized, 0, sizeof(pages_privatized)); + + mutex_pages_unlock(); + s_mutex_unlock(); +} + + +static void setup_forksupport(void) +{ + static bool fork_support_ready = false; + + if (!fork_support_ready) { + int res = pthread_atfork(forksupport_prepare, forksupport_parent, + forksupport_child); + assert(res == 0); + fork_support_ready = true; + } +} diff --git a/c7/stm/forksupport.h b/c7/stm/forksupport.h new file mode 100644 --- /dev/null +++ b/c7/stm/forksupport.h @@ -0,0 +1,2 @@ + +static void setup_forksupport(void); diff --git a/c7/stm/pages.h b/c7/stm/pages.h --- a/c7/stm/pages.h +++ b/c7/stm/pages.h @@ -39,6 +39,7 @@ static void page_privatize(uintptr_t pagenum); static void page_reshare(uintptr_t pagenum); +/* Note: don't ever do "mutex_pages_lock(); mutex_lock()" in that order */ static void mutex_pages_lock(void); static void mutex_pages_unlock(void); static bool _has_mutex_pages(void) __attribute__((unused)); diff --git a/c7/stm/setup.c b/c7/stm/setup.c --- a/c7/stm/setup.c +++ b/c7/stm/setup.c @@ -3,6 +3,38 @@ #endif +static char *setup_mmap(char *reason) +{ + char *result = mmap(NULL, TOTAL_MEMORY, + PROT_READ | PROT_WRITE, + MAP_PAGES_FLAGS, -1, 0); + if (result == MAP_FAILED) + stm_fatalerror("%s failed: %m\n", reason); + + /* The segment 0 is not used to run transactions, but contains the + shared copy of the pages. We mprotect all pages before so that + accesses fail, up to and including the pages corresponding to the + nurseries of the other segments. */ + mprotect(result, END_NURSERY_PAGE * 4096UL, PROT_NONE); + + long i; + for (i = 1; i <= NB_SEGMENTS; i++) { + char *segment_base = result + i * (NB_PAGES * 4096UL); + + /* 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); + + /* Pages in range(2, FIRST_READMARKER_PAGE) are never used */ + if (FIRST_READMARKER_PAGE > 2) + mprotect(segment_base + 8192, + (FIRST_READMARKER_PAGE - 2) * 4096UL, + PROT_NONE); + } + + return result; +} + void stm_setup(void) { /* Check that some values are acceptable */ @@ -20,38 +52,18 @@ (FIRST_READMARKER_PAGE * 4096UL)); assert(_STM_FAST_ALLOC <= NB_NURSERY_PAGES * 4096); - stm_object_pages = mmap(NULL, TOTAL_MEMORY, - PROT_READ | PROT_WRITE, - MAP_PAGES_FLAGS, -1, 0); - if (stm_object_pages == MAP_FAILED) - stm_fatalerror("initial stm_object_pages mmap() failed: %m\n"); - - /* The segment 0 is not used to run transactions, but to contain the - shared copy of the pages. We mprotect all pages before so that - accesses fail, up to and including the pages corresponding to the - nurseries of the other segments. */ - mprotect(stm_object_pages, END_NURSERY_PAGE * 4096UL, PROT_NONE); + stm_object_pages = setup_mmap("initial stm_object_pages mmap()"); long i; for (i = 1; 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); - /* Fill the TLS page (page 1) with 0xDC, for debugging */ memset(REAL_ADDRESS(segment_base, 4096), 0xDC, 4096); /* Make a "hole" at STM_PSEGMENT (which includes STM_SEGMENT) */ memset(REAL_ADDRESS(segment_base, STM_PSEGMENT), 0, sizeof(*STM_PSEGMENT)); - /* Pages in range(2, FIRST_READMARKER_PAGE) are never used */ - if (FIRST_READMARKER_PAGE > 2) - mprotect(segment_base + 8192, - (FIRST_READMARKER_PAGE - 2) * 4096UL, - PROT_NONE); - /* Initialize STM_PSEGMENT */ struct stm_priv_segment_info_s *pr = get_priv_segment(i); assert(1 <= i && i < 255); /* 255 is WL_VISITED in gcpage.c */ @@ -83,6 +95,7 @@ setup_nursery(); setup_gcpage(); setup_pages(); + setup_forksupport(); } void stm_teardown(void) diff --git a/c7/stmgc.c b/c7/stmgc.c --- a/c7/stmgc.c +++ b/c7/stmgc.c @@ -13,6 +13,7 @@ #include "stm/extra.h" #include "stm/fprintcolor.h" #include "stm/weakref.h" +#include "stm/forksupport.h" #include "stm/misc.c" #include "stm/list.c" @@ -30,3 +31,4 @@ #include "stm/extra.c" #include "stm/fprintcolor.c" #include "stm/weakref.c" +#include "stm/forksupport.c" _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit