[pypy-commit] stmgc default: Simplify the forking logic by enforcing that stm_object_pages are
arigo
noreply at buildbot.pypy.org
Mon Feb 9 15:57:16 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r1615:ac07eddb02d5
Date: 2015-02-09 15:57 +0100
http://bitbucket.org/pypy/stmgc/changeset/ac07eddb02d5/
Log: Simplify the forking logic by enforcing that stm_object_pages are
private pages all the way to END_NURSERY_PAGE, and shared pages
afterwards. Removes the need for page_is_null(), which seems one
the main sources of fork slowness.
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -309,18 +309,19 @@
/* force-reset all read markers to 0 */
char *readmarkers = REAL_ADDRESS(STM_SEGMENT->segment_base,
- FIRST_READMARKER_PAGE * 4096UL);
+ FIRST_OLD_RM_PAGE * 4096UL);
+ uintptr_t num_bytes = 4096UL *
+ (NB_READMARKER_PAGES - (FIRST_OLD_RM_PAGE - FIRST_READMARKER_PAGE));
+
dprintf(("reset_transaction_read_version: %p %ld\n", readmarkers,
- (long)(NB_READMARKER_PAGES * 4096UL)));
+ (long)num_bytes));
- if (mmap(readmarkers, NB_READMARKER_PAGES * 4096UL,
+ if (mmap(readmarkers, num_bytes,
PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PAGES_FLAGS, -1, 0) != readmarkers) {
- /* fall-back */
-#if STM_TESTS
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ -1, 0) != readmarkers) {
+ /* failed */
stm_fatalerror("reset_transaction_read_version: %m");
-#endif
- memset(readmarkers, 0, NB_READMARKER_PAGES * 4096UL);
}
STM_SEGMENT->transaction_read_version = 1;
}
diff --git a/c7/stm/forksupport.c b/c7/stm/forksupport.c
--- a/c7/stm/forksupport.c
+++ b/c7/stm/forksupport.c
@@ -12,16 +12,6 @@
static stm_thread_local_t *fork_this_tl;
static bool fork_was_in_transaction;
-static bool page_is_null(char *p)
-{
- long *q = (long *)p;
- long i;
- for (i = 0; i < 4096 / sizeof(long); i++)
- if (q[i] != 0)
- return false;
- return true;
-}
-
static void forksupport_prepare(void)
{
@@ -71,27 +61,6 @@
int big_copy_fd;
char *big_copy = setup_mmap("stmgc's fork support", &big_copy_fd);
- /* Copy each of the segment infos into the new mmap, nurseries,
- and associated read markers
- */
- long i;
- for (i = 1; i <= NB_SEGMENTS; i++) {
- char *src, *dst;
- struct stm_priv_segment_info_s *psrc = get_priv_segment(i);
- dst = big_copy + (((char *)psrc) - stm_object_pages);
- *(struct stm_priv_segment_info_s *)dst = *psrc;
-
- src = get_segment_base(i) + FIRST_READMARKER_PAGE * 4096UL;
- dst = big_copy + (src - stm_object_pages);
- long j;
- for (j = 0; j < END_NURSERY_PAGE - FIRST_READMARKER_PAGE; j++) {
- if (!page_is_null(src))
- pagecopy(dst, src);
- src += 4096;
- dst += 4096;
- }
- }
-
/* Copy all the data from the two ranges of objects (large, small)
into the new mmap
*/
@@ -201,16 +170,24 @@
just release these locks early */
s_mutex_unlock();
- /* Move the copy of the mmap over the old one, overwriting it
- and thus freeing the old mapping in this process
+ /* Move the copy of the mmap over the old one, overwriting it,
+ with "holes" for each segment's read markers (which are already
+ MAP_PRIVATE and shouldn't be overwritten). Then free the copy.
*/
assert(fork_big_copy != NULL);
assert(stm_object_pages != NULL);
- void *res = mremap(fork_big_copy, TOTAL_MEMORY, TOTAL_MEMORY,
- MREMAP_MAYMOVE | MREMAP_FIXED,
- stm_object_pages);
- if (res != stm_object_pages)
- stm_fatalerror("after fork: mremap failed: %m");
+
+ long j;
+ for (j = 0; j <= NB_SEGMENTS; j++) {
+ char *dst = get_segment_base(j) + END_NURSERY_PAGE * 4096UL;
+ char *src = fork_big_copy + (dst - stm_object_pages);
+ uintptr_t num_bytes = (NB_PAGES - END_NURSERY_PAGE) * 4096UL;
+ void *res = mremap(src, num_bytes, num_bytes,
+ MREMAP_MAYMOVE | MREMAP_FIXED, dst);
+ if (res != dst)
+ stm_fatalerror("after fork: mremap failed: %m");
+ }
+ munmap(fork_big_copy, TOTAL_MEMORY);
fork_big_copy = NULL;
close_fd_mmap(stm_object_pages_fd);
stm_object_pages_fd = fork_big_copy_fd;
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -99,9 +99,21 @@
stm_object_pages = setup_mmap("initial stm_object_pages mmap()",
&stm_object_pages_fd);
+
+ /* remap MAP_PRIVATE pages on the initial part of each segment
+ in stm_object_pages */
+ long i;
+ for (i = 0; i <= NB_SEGMENTS; i++) {
+ char *res;
+ res = mmap(get_segment_base(i), END_NURSERY_PAGE * 4096UL,
+ PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ -1, 0);
+ if (res == MAP_FAILED)
+ stm_fatalerror("mmap(private) failed: %m");
+ }
setup_protection_settings();
- long i;
for (i = 1; i <= NB_SEGMENTS; i++) {
char *segment_base = get_segment_base(i);
@@ -133,16 +145,11 @@
pr->old_objects_with_light_finalizers = list_create();
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * i;
highest_overflow_number = pr->overflow_number;
- pr->pub.transaction_read_version = 0xff;
+ pr->pub.transaction_read_version = 0;
}
/* The pages are shared lazily, as remap_file_pages() takes a relatively
long time for each page.
-
- The read markers are initially zero, but we set anyway
- transaction_read_version to 0xff in order to force the first
- transaction to "clear" the read markers by mapping a different,
- private range of addresses.
*/
setup_sync();
More information about the pypy-commit
mailing list