Author: Armin Rigo <[email protected]>
Branch: c8-private-pages
Changeset: r1510:e305d59e0a3d
Date: 2014-12-02 21:07 +0100
http://bitbucket.org/pypy/stmgc/changeset/e305d59e0a3d/
Log: in-progress
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -3,20 +3,6 @@
#endif
-#ifdef NDEBUG
-#define EVENTUALLY(condition) {/* nothing */}
-#else
-#define EVENTUALLY(condition) \
- { \
- if (!(condition)) { \
- acquire_privatization_lock(STM_SEGMENT->segment_num);\
- if (!(condition)) \
- stm_fatalerror("fails: " #condition); \
- release_privatization_lock(STM_SEGMENT->segment_num);\
- } \
- }
-#endif
-
/* General helper: copies objects into our own segment, from some
source described by a range of 'struct stm_undo_s'. Maybe later
we could specialize this function to avoid the checks in the
@@ -280,7 +266,7 @@
dprintf(("_stm_validate(%p)\n", free_if_abort));
/* go from last known entry in commit log to the
most current one and apply all changes done
- by other transactions. Abort if we read one of
+ by other transactions. Abort if we have read one of
the committed objs. */
struct stm_commit_log_entry_s *first_cl =
STM_PSEGMENT->last_commit_log_entry;
struct stm_commit_log_entry_s *next_cl, *last_cl, *cl;
@@ -346,6 +332,10 @@
segment_really_copied_from |= (1UL << cl->segment_num);
import_objects(cl->segment_num, -1, undo, end);
+
+ copy_bk_objs_in_page_from(
+ segnum, -1, /* any page */
+ !needs_abort); /* if we abort, we still want to copy
everything */
}
/* last fully validated entry */
@@ -355,18 +345,15 @@
}
assert(cl == last_cl);
- OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS));
- int segnum;
- for (segnum = 0; segnum < NB_SEGMENTS; segnum++) {
- if (segment_really_copied_from & (1UL << segnum)) {
- /* here we can actually have our own modified version, so
- make sure to only copy things that are not modified in our
- segment... (if we do not abort) */
- copy_bk_objs_in_page_from(
- segnum, -1, /* any page */
- !needs_abort); /* if we abort, we still want to copy
everything */
- }
- }
+ /* OPT_ASSERT(segment_really_copied_from <= ((1UL << NB_SEGMENTS) -
1)); */
+ /* int segnum; */
+ /* for (segnum = 0; segnum < NB_SEGMENTS; segnum++) { */
+ /* if (segment_really_copied_from & (1UL << segnum)) { */
+ /* /\* here we can actually have our own modified version, so
*/
+ /* make sure to only copy things that are not modified in
our */
+ /* segment... (if we do not abort) *\/ */
+ /* } */
+ /* } */
}
/* done with modifications */
@@ -654,7 +641,7 @@
enter_safe_point_if_requested();
dprintf(("> start_transaction\n"));
- s_mutex_unlock();
+ s_mutex_unlock(); // XXX it's probably possible to not acquire this here
uint8_t old_rv = STM_SEGMENT->transaction_read_version;
STM_SEGMENT->transaction_read_version = old_rv + 1;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -73,7 +73,7 @@
struct tree_s *young_outside_nursery;
struct tree_s *nursery_objects_shadows;
- uint8_t privatization_lock;
+ uint8_t privatization_lock; // XXX KILL
uint8_t safe_point;
uint8_t transaction_state;
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -5,9 +5,8 @@
static void setup_gcpage(void)
{
- /* XXXXXXX should use stm_file_pages, no? */
- uninitialized_page_start = stm_file_pages;
- uninitialized_page_stop = stm_file_pages + NB_SHARED_PAGES * 4096UL;
+ //uninitialized_page_start = stm_file_pages;
+ //uninitialized_page_stop = stm_file_pages + NB_SHARED_PAGES * 4096UL;
}
static void teardown_gcpage(void)
diff --git a/c8/stm/gcpage.h b/c8/stm/gcpage.h
--- a/c8/stm/gcpage.h
+++ b/c8/stm/gcpage.h
@@ -2,8 +2,8 @@
/* Granularity when grabbing more unused pages: take 50 at a time */
#define GCPAGE_NUM_PAGES 50
-static char *uninitialized_page_start; /* within segment 0 */
-static char *uninitialized_page_stop;
+//static char *uninitialized_page_start; /* within segment 0 */
+//static char *uninitialized_page_stop;
static void setup_gcpage(void);
static void teardown_gcpage(void);
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -16,71 +16,26 @@
/************************************************************/
-static void pages_initialize_shared_for(long segnum, uintptr_t pagenum,
uintptr_t count)
+
+static void page_mark_accessible(long segnum, uintptr_t pagenum)
{
- /* call remap_file_pages() to make all pages in the range(pagenum,
- pagenum+count) PAGE_SHARED in segnum, and PAGE_NO_ACCESS in other
segments
- initialize to |S|N|N|N| */
+ assert(get_page_status_in(segnum, pagenum) == PAGE_NO_ACCESS);
+ dprintf(("page_mark_accessible(%lu) in seg:%ld\n", pagenum, segnum));
- dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum, pagenum +
count));
+ mprotect(get_virtual_page(segnum, pagenum), 4096, PROT_READ | PROT_WRITE);
- assert(all_privatization_locks_acquired());
-
- assert(pagenum < NB_PAGES);
- if (count == 0)
- return;
-
- /* already shared after setup.c (also for the other count-1 pages) */
- assert(get_page_status_in(segnum, pagenum) == PAGE_SHARED);
-
- /* make other segments NO_ACCESS: */
- uintptr_t i;
- for (i = 0; i < NB_SEGMENTS; i++) {
- if (i != segnum) {
- char *segment_base = get_segment_base(i);
- mprotect(segment_base + pagenum * 4096UL,
- count * 4096UL, PROT_NONE);
-
- /* char *result = mmap( */
- /* segment_base + pagenum * 4096UL, */
- /* count * 4096UL, */
- /* PROT_NONE, */
- /* MAP_FIXED|MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, */
- /* -1, 0); */
- /* if (result == MAP_FAILED) */
- /* stm_fatalerror("pages_initialize_shared failed (mmap):
%m"); */
-
-
- long amount = count;
- while (amount-->0) {
- set_page_status_in(i, pagenum + amount, PAGE_NO_ACCESS);
- }
- }
- }
+ /* set this flag *after* we un-protected it, because XXX later */
+ set_page_status_in(segnum, pagenum, PAGE_ACCESSIBLE);
}
+static void page_mark_inaccessible(long segnum, uintptr_t pagenum)
+{
+ assert(get_page_status_in(segnum, pagenum) == PAGE_ACCESSIBLE);
+ dprintf(("page_mark_inaccessible(%lu) in seg:%ld\n", pagenum, segnum));
-static void page_privatize_in(int segnum, uintptr_t pagenum)
-{
-#ifndef NDEBUG
- long l;
- for (l = 0; l < NB_SEGMENTS; l++) {
- assert(get_priv_segment(l)->privatization_lock);
- }
-#endif
- assert(get_page_status_in(segnum, pagenum) == PAGE_NO_ACCESS);
- dprintf(("page_privatize(%lu) in seg:%d\n", pagenum, segnum));
+ set_page_status_in(segnum, pagenum, PAGE_ACCESSIBLE);
- char *addr = (char*)(get_virt_page_of(segnum, pagenum) * 4096UL);
- char *result = mmap(
- addr, 4096UL, PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_NORESERVE,
- stm_object_pages_fd, get_file_page_of(pagenum) * 4096UL);
- if (result == MAP_FAILED)
- stm_fatalerror("page_privatize_in failed (mmap): %m");
-
- set_page_status_in(segnum, pagenum, PAGE_PRIVATE);
-
- volatile char *dummy = REAL_ADDRESS(get_segment_base(segnum),
pagenum*4096UL);
- *dummy = *dummy; /* force copy-on-write from shared page */
+ char *addr = get_virtual_page(segnum, pagenum);
+ madvise(get_virtual_page(segnum, pagenum), 4096, MADV_DONTNEED);
+ mprotect(addr, 4096, PROT_NONE);
}
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -3,90 +3,61 @@
logical page
We have virtual pages: one virtual address can point in some
virtual page. We have NB_SEGMENTS virtual pages per logical page.
- We have file pages: they correspond mostly to physical memory pages
- used for mmap/remap_file_pages
- A logical page is SHARED iff all NB_SEGMENTS virtual pages point to
- one file page, and thus to the same logical page.
-
- A logical page becomes PRIVATE if one virtual page still maps to the
- original file page, and all others turn read protected.
- -> only one can modify it.
-
- A logical page can also be "PRIVATE IN A SEGMENT", referring to
- the virtual page of the segment having its own file page backing.
- It also implies the logical page is not read protected.
+ Each virtual page is either accessible, or PAGE_NO_ACCESS (and then
+ has no underlying memory).
*/
#define PAGE_FLAG_START END_NURSERY_PAGE
#define PAGE_FLAG_END NB_PAGES
-/* == NB_SHARED_PAGES */
struct page_shared_s {
-#if NB_SEGMENTS <= 4
+#if NB_SEGMENTS <= 8
uint8_t by_segment;
-#elif NB_SEGMENTS <= 8
+#elif NB_SEGMENTS <= 16
uint16_t by_segment;
-#elif NB_SEGMENTS <= 16
+#elif NB_SEGMENTS <= 32
uint32_t by_segment;
-#elif NB_SEGMENTS <= 32
+#elif NB_SEGMENTS <= 64
uint64_t by_segment;
#else
-# error "NB_SEGMENTS > 32 not supported right now"
+# error "NB_SEGMENTS > 64 not supported right now"
#endif
};
enum {
- PAGE_SHARED = 0,
- PAGE_PRIVATE = 1,
- PAGE_NO_ACCESS = 2,
+ PAGE_NO_ACCESS = 0,
+ PAGE_ACCESSIBLE = 1
};
-static struct page_shared_s pages_status[NB_SHARED_PAGES];
+static struct page_shared_s pages_status[PAGE_FLAG_END - PAGE_FLAG_START];
-static void pages_initialize_shared_for(long segnum, uintptr_t pagenum,
uintptr_t count);
-static void page_privatize_in(int segnum, uintptr_t pagenum);
+static void page_mark_accessible(long segnum, uintptr_t pagenum);
+static void page_mark_inaccessible(long segnum, uintptr_t pagenum);
-
-
-static inline uintptr_t get_virt_page_of(long segnum, uintptr_t pagenum)
+static inline char *get_virtual_page(long segnum, uintptr_t pagenum)
{
/* logical page -> virtual page */
- return (uintptr_t)get_segment_base(segnum) / 4096UL + pagenum;
+ return get_segment_base(segnum) + pagenum * 4096;
}
-static inline uintptr_t get_file_page_of(uintptr_t pagenum)
+static inline bool get_page_status_in(long segnum, uintptr_t pagenum)
{
- /* logical page -> file page */
- return pagenum - PAGE_FLAG_START;
+ OPT_ASSERT(segnum < 8 * sizeof(struct page_shared_s));
+ volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
+ &pages_status[pagenum - PAGE_FLAG_START];
+
+ return (ps->by_segment >> segnum) & 1;
}
-static inline uintptr_t get_page_of_file_page(uintptr_t file_page)
+static inline void set_page_status_in(long segnum, uintptr_t pagenum,
+ bool status)
{
- return file_page + END_NURSERY_PAGE;
-}
-
-static inline uint8_t get_page_status_in(long segnum, uintptr_t pagenum)
-{
- int seg_shift = segnum * 2;
- OPT_ASSERT(seg_shift < 8 * sizeof(struct page_shared_s));
+ OPT_ASSERT(segnum < 8 * sizeof(struct page_shared_s));
volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
- &pages_status[get_file_page_of(pagenum)];
-
- return (ps->by_segment >> seg_shift) & 3;
-}
-
-static inline void set_page_status_in(long segnum, uintptr_t pagenum, uint8_t
status)
-{
- OPT_ASSERT(status < 3);
-
- int seg_shift = segnum * 2;
- OPT_ASSERT(seg_shift < 8 * sizeof(struct page_shared_s));
- volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
- &pages_status[get_file_page_of(pagenum)];
+ &pages_status[pagenum - PAGE_FLAG_START];
assert(status != get_page_status_in(segnum, pagenum));
- ps->by_segment &= ~(3UL << seg_shift); /* clear */
- ps->by_segment |= status << seg_shift; /* set */
+ __sync_fetch_and_xor(&ps->by_segment, 1UL << segnum); /* invert the flag */
}
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -7,56 +7,14 @@
static void setup_mmap(char *reason)
{
- char name[] = "/__stmgc_c8__";
-
- /* Create the big shared memory object, and immediately unlink it.
- There is a small window where if this process is killed the
- object is left around. It doesn't seem possible to do anything
- about it...
- */
- stm_object_pages_fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
- shm_unlink(name);
-
- if (stm_object_pages_fd == -1)
- stm_fatalerror("%s failed (stm_open): %m", reason);
-
- if (ftruncate(stm_object_pages_fd, NB_SHARED_PAGES * 4096UL) != 0)
- stm_fatalerror("%s failed (ftruncate): %m", reason);
-
- stm_file_pages = mmap(NULL, NB_SHARED_PAGES * 4096UL,
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_NORESERVE,
- stm_object_pages_fd, 0);
-
- if (stm_file_pages == MAP_FAILED)
- stm_fatalerror("%s failed (mmap): %m", reason);
-
-
/* reserve the whole virtual memory space of the program for
- all segments: */
- stm_object_pages = mmap(NULL, TOTAL_MEMORY,
- PROT_READ | PROT_WRITE,
+ all segments: (for now in one big block, but later could be
+ allocated per-segment) */
+ stm_object_pages = mmap(NULL, TOTAL_MEMORY, PROT_NONE,
MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS,
-1, 0);
if (stm_object_pages == MAP_FAILED)
stm_fatalerror("%s failed (mmap): %m", reason);
-
- /* remap the shared part of the segments to the file pages */
- long l;
- for (l = 0; l < NB_SEGMENTS; l++) {
- char *result = mmap(
- stm_object_pages + (l * NB_PAGES + END_NURSERY_PAGE) * 4096UL, /*
addr */
- NB_SHARED_PAGES * 4096UL, /* len */
- PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_SHARED | MAP_NORESERVE,
- stm_object_pages_fd, 0); /* file & offset */
- if (result == MAP_FAILED)
- stm_fatalerror("%s failed (mmap): %m", reason);
- }
-}
-static void close_fd_mmap(int map_fd)
-{
- close(map_fd);
}
static void setup_protection_settings(void)
@@ -65,17 +23,13 @@
for (i = 0; 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);
+ /* In each segment, the second page is where STM_SEGMENT lands. */
+ mprotect(segment_base + 4096, 4096, PROT_READ | PROT_WRITE);
- /* Pages in range(2, FIRST_READMARKER_PAGE) are never used */
- if (FIRST_READMARKER_PAGE > 2)
- mprotect(segment_base + 2 * 4096,
- (FIRST_READMARKER_PAGE - 2) * 4096UL,
- PROT_NONE);
-
- /* STM_SEGMENT-TL is in page 1 */
+ /* Make the read marker pages accessible, as well as the nursery. */
+ mprotect(segment_base + FIRST_READMARKER_PAGE * 4096,
+ (NB_READMARKER_PAGES + NB_NURSERY_PAGES) * 4096,
+ PROT_READ | PROT_WRITE);
}
}
@@ -184,7 +138,6 @@
stm_object_pages = NULL;
commit_log_root.next = NULL; /* xxx:free them */
commit_log_root.segment_num = -1;
- close_fd_mmap(stm_object_pages_fd);
teardown_sync();
teardown_gcpage();
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit