[pypy-commit] stmgc default: uhm, try to do atomic privatization of pages
Raemi
noreply at buildbot.pypy.org
Wed Sep 10 15:25:35 CEST 2014
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch:
Changeset: r1382:777200bdb987
Date: 2014-09-10 15:27 +0200
http://bitbucket.org/pypy/stmgc/changeset/777200bdb987/
Log: uhm, try to do atomic privatization of pages
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -224,8 +224,7 @@
for (i = 1; i < NB_SEGMENTS; i++) {
assert(!is_private_log_page_in(i, pagenum));
- page_privatize_in(i, pagenum);
- pagecopy((char*)(get_virt_page_of(i, pagenum) * 4096UL), src);
+ page_privatize_in(i, pagenum, src);
}
set_page_private_in(0, pagenum);
@@ -256,23 +255,23 @@
struct object_s *bk_obj = malloc(obj_size);
memcpy(bk_obj, realobj, obj_size);
- if (is_shared_log_page(first_page)) {
- /* acquire all privatization locks, make private and
- read protect others */
- long i;
- uintptr_t page;
- for (i = 0; i < NB_SEGMENTS; i++) {
- acquire_privatization_lock(i);
- }
- for (page = first_page; page <= end_page; page++) {
+ /* if there are shared pages, privatize them */
+
+ uintptr_t page;
+ for (page = first_page; page <= end_page; page++) {
+ if (is_shared_log_page(page)) {
+ long i;
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ acquire_privatization_lock(i);
+ }
if (is_shared_log_page(page))
_privatize_shared_page(page);
- }
- for (i = NB_SEGMENTS-1; i >= 0; i--) {
- release_privatization_lock(i);
+ for (i = NB_SEGMENTS-1; i >= 0; i--) {
+ release_privatization_lock(i);
+ }
}
}
- /* page not shared anymore. but we still may have
+ /* pages not shared anymore. but we still may have
only a read protected page ourselves: */
acquire_privatization_lock(my_segnum);
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -32,6 +32,7 @@
#define FIRST_OLD_RM_PAGE (OLD_RM_START / 4096UL)
#define NB_READMARKER_PAGES (FIRST_OBJECT_PAGE - FIRST_READMARKER_PAGE)
+#define TMP_COPY_PAGE 1 /* HACK */
enum /* stm_flags */ {
GCFLAG_WRITE_BARRIER = _STM_GCFLAG_WRITE_BARRIER,
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -15,7 +15,14 @@
static void setup_N_pages(char *pages_addr, uint64_t num)
{
+ long i;
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ acquire_privatization_lock(i);
+ }
pages_initialize_shared((pages_addr - stm_object_pages) / 4096UL, num);
+ for (i = NB_SEGMENTS-1; i >= 0; i--) {
+ release_privatization_lock(i);
+ }
}
@@ -43,7 +50,7 @@
}
dprintf(("allocate_outside_nursery_large(%lu): %p, seg=%d, page=%lu\n",
size, addr, get_segment_of_linear_address(addr),
- (addr - STM_SEGMENT->segment_base) / 4096UL));
+ (addr - get_segment_base(get_segment_of_linear_address(addr))) / 4096UL));
spinlock_release(lock_growth_large);
return addr;
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -34,7 +34,8 @@
/* assert remappings follow the rule that page N in one segment
can only be remapped to page N in another segment */
- assert(((addr - stm_object_pages) / 4096UL - pgoff) % NB_PAGES == 0);
+ assert(IMPLY(((addr - stm_object_pages) / 4096UL) != TMP_COPY_PAGE,
+ ((addr - stm_object_pages) / 4096UL - pgoff) % NB_PAGES == 0));
#ifdef USE_REMAP_FILE_PAGES
int res = remap_file_pages(addr, size, 0, pgoff, 0);
@@ -58,6 +59,12 @@
segment 0. */
dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum,
pagenum + count));
+#ifndef NDEBUG
+ long l;
+ for (l = 0; l < NB_SEGMENTS; l++) {
+ assert(get_priv_segment(l)->privatization_lock);
+ }
+#endif
assert(pagenum < NB_PAGES);
if (count == 0)
return;
@@ -79,10 +86,15 @@
}
}
-static void page_privatize_in(int segnum, uintptr_t pagenum)
+
+static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from)
{
- /* hopefully holding the lock */
- assert(get_priv_segment(segnum)->privatization_lock);
+#ifndef NDEBUG
+ long l;
+ for (l = 0; l < NB_SEGMENTS; l++) {
+ assert(get_priv_segment(l)->privatization_lock);
+ }
+#endif
/* check this thread's 'pages_privatized' bit */
uint64_t bitmask = 1UL << segnum;
@@ -103,6 +115,14 @@
attempt to group together many calls to d_remap_file_pages() in
succession) */
uintptr_t pagenum_in_file = NB_PAGES * segnum + pagenum;
+ char *tmp_page = stm_object_pages + TMP_COPY_PAGE * 4096UL;
+ /* first remap to TMP_PAGE, then copy stuff there (to the underlying
+ file page), then remap this file-page hopefully atomically to the
+ segnum's virtual page */
+ d_remap_file_pages(tmp_page, 4096, pagenum_in_file);
+ pagecopy(tmp_page, initialize_from);
+ write_fence();
+
char *new_page = stm_object_pages + pagenum_in_file * 4096UL;
d_remap_file_pages(new_page, 4096, pagenum_in_file);
}
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -40,7 +40,7 @@
static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
-static void page_privatize_in(int segnum, uintptr_t pagenum);
+static void page_privatize_in(int segnum, uintptr_t pagenum, char *initialize_from);
static inline uintptr_t get_virt_page_of(long segnum, uintptr_t pagenum)
{
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -63,11 +63,19 @@
NULL accesses land. We mprotect it so that accesses fail. */
mprotect(segment_base, 4096, PROT_NONE);
+ /* TMP_COPY_PAGE is used for atomic privatization */
+ mprotect(segment_base + TMP_COPY_PAGE * 4096UL,
+ 4096UL, PROT_READ|PROT_WRITE);
+
/* Pages in range(2, FIRST_READMARKER_PAGE) are never used */
- if (FIRST_READMARKER_PAGE > 2)
- mprotect(segment_base + 8192,
- (FIRST_READMARKER_PAGE - 2) * 4096UL,
+ if (FIRST_READMARKER_PAGE > TMP_COPY_PAGE + 1)
+ mprotect(segment_base + (TMP_COPY_PAGE + 1) * 4096,
+ (FIRST_READMARKER_PAGE - TMP_COPY_PAGE - 1) * 4096UL,
PROT_NONE);
+
+ /* STM_SEGMENT */
+ mprotect(segment_base + ((uintptr_t)STM_SEGMENT / 4096UL) * 4096UL,
+ 4096UL, PROT_READ|PROT_WRITE);
}
}
@@ -75,11 +83,13 @@
void stm_setup(void)
{
/* Check that some values are acceptable */
+ assert(TMP_COPY_PAGE > 0 && TMP_COPY_PAGE <= 1);
+ assert(TMP_COPY_PAGE * 4096 + 4096 <= ((uintptr_t)STM_SEGMENT));
+ assert((uintptr_t)STM_SEGMENT == (uintptr_t)STM_PSEGMENT);
+ assert(((uintptr_t)STM_PSEGMENT) + sizeof(*STM_PSEGMENT) <= FIRST_READMARKER_PAGE*4096);
+
assert(NB_SEGMENTS <= NB_SEGMENTS_MAX);
- assert(4096 <= ((uintptr_t)STM_SEGMENT));
- assert((uintptr_t)STM_SEGMENT == (uintptr_t)STM_PSEGMENT);
- assert(((uintptr_t)STM_PSEGMENT) + sizeof(*STM_PSEGMENT) <= 8192);
- assert(2 <= FIRST_READMARKER_PAGE);
+ assert(TMP_COPY_PAGE < FIRST_READMARKER_PAGE);
assert(FIRST_READMARKER_PAGE * 4096UL <= READMARKER_START);
assert(READMARKER_START < READMARKER_END);
assert(READMARKER_END <= 4096UL * FIRST_OBJECT_PAGE);
@@ -98,7 +108,7 @@
char *segment_base = get_segment_base(i);
/* Fill the TLS page (page 1) with 0xDC, for debugging */
- memset(REAL_ADDRESS(segment_base, 4096), 0xDC, 4096);
+ memset(REAL_ADDRESS(segment_base, ((uintptr_t)STM_PSEGMENT/4096) * 4096), 0xDC, 4096);
/* Make a "hole" at STM_PSEGMENT (which includes STM_SEGMENT) */
memset(REAL_ADDRESS(segment_base, STM_PSEGMENT), 0,
sizeof(*STM_PSEGMENT));
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -34,7 +34,7 @@
uintptr_t nursery_end;
struct stm_thread_local_s *running_thread;
};
-#define STM_SEGMENT ((stm_segment_info_t *)4352)
+#define STM_SEGMENT ((stm_segment_info_t *)8192)
struct stm_shadowentry_s {
More information about the pypy-commit
mailing list