Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit