[pypy-commit] stmgc default: start with some signal handling
Raemi
noreply at buildbot.pypy.org
Wed Sep 3 16:44:20 CEST 2014
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch:
Changeset: r1342:d02e51a1b9e1
Date: 2014-09-03 16:45 +0200
http://bitbucket.org/pypy/stmgc/changeset/d02e51a1b9e1/
Log: start with some signal handling
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -2,9 +2,23 @@
# error "must be compiled via stmgc.c"
#endif
+#include <signal.h>
+
+
+/* ############# signal handler ############# */
+
+void _signal_handler(int sig, siginfo_t *siginfo, void *context)
+{
+
+ if (siginfo->si_addr == NULL) {
+ /* send to GDB */
+ kill(getpid(), SIGINT);
+ }
+}
/* ############# commit log ############# */
+
void _dbg_print_commit_log()
{
struct stm_commit_log_entry_s *cl = &commit_log_root;
@@ -90,6 +104,26 @@
stm_read(obj);
+ /* make other segments trap if accessing this object */
+ uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
+ char *realobj;
+ size_t obj_size;
+ uintptr_t i, end_page;
+
+ realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+ end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
+
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ if (i == STM_SEGMENT->segment_num)
+ continue;
+
+ char *segment_base = get_segment_base(i);
+ mprotect(segment_base + first_page * 4096,
+ (end_page - first_page + 1) * 4096, PROT_NONE);
+ dprintf(("prot %lu, len=%lu in seg %d\n", first_page, (end_page - first_page + 1), i));
+ }
+
LIST_APPEND(STM_PSEGMENT->modified_old_objects, obj);
LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
@@ -162,66 +196,6 @@
/************************************************************/
-static void _page_wise_synchronize_object_now(object_t *obj)
-{
- uintptr_t start = (uintptr_t)obj;
- uintptr_t first_page = start / 4096UL;
-
- char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
- ssize_t obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
- assert(obj_size >= 16);
- uintptr_t end = start + obj_size;
- uintptr_t last_page = (end - 1) / 4096UL;
- long i, myself = STM_SEGMENT->segment_num;
-
- for (; first_page <= last_page; first_page++) {
-
- uintptr_t copy_size;
- if (first_page == last_page) {
- /* this is the final fragment */
- copy_size = end - start;
- }
- else {
- /* this is a non-final fragment, going up to the
- page's end */
- copy_size = 4096 - (start & 4095);
- }
- /* double-check that the result fits in one page */
- assert(copy_size > 0);
- assert(copy_size + (start & 4095) <= 4096);
-
- char *dst, *src;
- src = REAL_ADDRESS(STM_SEGMENT->segment_base, start);
- for (i = 0; i < NB_SEGMENTS; i++) {
- if (i == myself)
- continue;
-
- dst = REAL_ADDRESS(get_segment_base(i), start);
- if (is_private_page(i, first_page)) {
- /* The page is a private page. We need to diffuse this
- fragment of object from the shared page to this private
- page. */
- if (copy_size == 4096)
- pagecopy(dst, src);
- else
- memcpy(dst, src, copy_size);
- }
- else {
- assert(!memcmp(dst, src, copy_size)); /* same page */
- }
- }
-
- start = (start + 4096) & ~4095;
- }
-}
-
-void _push_obj_to_other_segments(object_t *obj)
-{
- acquire_privatization_lock();
- _page_wise_synchronize_object_now(obj);
- release_privatization_lock();
-}
-
static void _finish_transaction()
{
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -20,7 +20,7 @@
#define MAP_PAGES_FLAGS (MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE)
#define NB_NURSERY_PAGES (STM_GC_NURSERY/4)
-#define TOTAL_MEMORY (NB_PAGES * 4096UL * (1 + NB_SEGMENTS))
+#define TOTAL_MEMORY (NB_PAGES * 4096UL * NB_SEGMENTS)
#define READMARKER_END ((NB_PAGES * 4096UL) >> 4)
#define FIRST_OBJECT_PAGE ((READMARKER_END + 4095) / 4096UL)
#define FIRST_NURSERY_PAGE FIRST_OBJECT_PAGE
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,7 @@
static void setup_N_pages(char *pages_addr, uint64_t num)
{
- pages_initialize_private((pages_addr - stm_object_pages) / 4096UL, num);
+ pages_initialize_shared((pages_addr - stm_object_pages) / 4096UL, num);
}
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -139,9 +139,6 @@
_collect_now(obj);
- /* XXX: only if commit now and only for big objs */
- _push_obj_to_other_segments(obj);
-
/* the list could have moved while appending */
lst = STM_PSEGMENT->objects_pointing_to_nursery;
}
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -16,31 +16,55 @@
/************************************************************/
+static void d_remap_file_pages(char *addr, size_t size, ssize_t pgoff)
+{
+ dprintf(("remap_file_pages: 0x%lx bytes: (seg%ld %p) --> (seg%ld %p)\n",
+ (long)size,
+ (long)((addr - stm_object_pages) / 4096UL) / NB_PAGES,
+ (void *)((addr - stm_object_pages) % (4096UL * NB_PAGES)),
+ (long)pgoff / NB_PAGES,
+ (void *)((pgoff % NB_PAGES) * 4096UL)));
+ assert(size % 4096 == 0);
+ assert(size <= TOTAL_MEMORY);
+ assert(((uintptr_t)addr) % 4096 == 0);
+ assert(addr >= stm_object_pages);
+ assert(addr <= stm_object_pages + TOTAL_MEMORY - size);
+ assert(pgoff >= 0);
+ assert(pgoff <= (TOTAL_MEMORY - size) / 4096UL);
-static void pages_initialize_private(uintptr_t pagenum, uintptr_t count)
+ /* 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);
+
+#ifdef USE_REMAP_FILE_PAGES
+ int res = remap_file_pages(addr, size, 0, pgoff, 0);
+ if (UNLIKELY(res < 0))
+ stm_fatalerror("remap_file_pages: %m");
+#else
+ char *res = mmap(addr, size,
+ PROT_READ | PROT_WRITE,
+ (MAP_PAGES_FLAGS & ~MAP_ANONYMOUS) | MAP_FIXED,
+ stm_object_pages_fd, pgoff * 4096UL);
+ if (UNLIKELY(res != addr))
+ stm_fatalerror("mmap (remapping page): %m");
+#endif
+}
+
+
+static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count)
{
- dprintf(("pages_initialize_private: 0x%ld - 0x%ld\n", pagenum,
+ /* call remap_file_pages() to make all pages in the range(pagenum,
+ pagenum+count) refer to the same physical range of pages from
+ segment 0. */
+ dprintf(("pages_initialize_shared: 0x%ld - 0x%ld\n", pagenum,
pagenum + count));
assert(pagenum < NB_PAGES);
if (count == 0)
return;
-
- long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
- spinlock_acquire(get_priv_segment(i)->privatization_lock);
- }
-
- while (count-->0) {
- for (i = 0; i < NB_SEGMENTS; i++) {
- uint64_t bitmask = 1UL << i;
- volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
- &pages_privatized[pagenum + count - PAGE_FLAG_START];
-
- ps->by_segment |= bitmask;
- }
- }
-
- for (i = NB_SEGMENTS-1; i >= 0; i--) {
- spinlock_release(get_priv_segment(i)->privatization_lock);
+ uintptr_t i;
+ for (i = 1; i < NB_SEGMENTS; i++) {
+ char *segment_base = get_segment_base(i);
+ d_remap_file_pages(segment_base + pagenum * 4096UL,
+ count * 4096UL, pagenum);
}
}
diff --git a/c8/stm/pages.h b/c8/stm/pages.h
--- a/c8/stm/pages.h
+++ b/c8/stm/pages.h
@@ -20,8 +20,7 @@
static struct page_shared_s pages_privatized[PAGE_FLAG_END - PAGE_FLAG_START];
-static void pages_initialize_private(uintptr_t pagenum, uintptr_t count);
-
+static void pages_initialize_shared(uintptr_t pagenum, uintptr_t count);
static inline bool is_private_page(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
@@ -2,6 +2,7 @@
# error "must be compiled via stmgc.c"
#endif
+#include <signal.h>
#ifdef USE_REMAP_FILE_PAGES
static char *setup_mmap(char *reason, int *ignored)
@@ -67,9 +68,32 @@
mprotect(segment_base + 8192,
(FIRST_READMARKER_PAGE - 2) * 4096UL,
PROT_NONE);
+
+ if (i != 0) {
+ /* let's give all pages to segment 0 at first and make them
+ write-inaccessible everywhere else */
+ mprotect(segment_base + END_NURSERY_PAGE * 4096,
+ (NB_PAGES - END_NURSERY_PAGE) * 4096,
+ PROT_READ);
+ }
}
}
+static void setup_signal_handler(void)
+{
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+
+ act.sa_sigaction = &_signal_handler;
+ /* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
+ act.sa_flags = SA_SIGINFO;
+
+ if (sigaction(SIGSEGV, &act, NULL) < 0) {
+ perror ("sigaction");
+ abort();
+ }
+}
+
void stm_setup(void)
{
/* Check that some values are acceptable */
@@ -89,6 +113,7 @@
stm_object_pages = setup_mmap("initial stm_object_pages mmap()",
&stm_object_pages_fd);
setup_protection_settings();
+ setup_signal_handler();
long i;
for (i = 0; i < NB_SEGMENTS; i++) {
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -46,7 +46,6 @@
char *_stm_get_segment_base(long index);
bool _stm_in_transaction(stm_thread_local_t *tl);
int _stm_get_flags(object_t *obj);
-void _push_obj_to_other_segments(object_t *obj);
object_t *_stm_allocate_old(ssize_t size_rounded_up);
long stm_can_move(object_t *obj);
@@ -244,14 +243,12 @@
o = lib._stm_allocate_old(size)
tid = 42 + size
lib._set_type_id(o, tid)
- lib._push_obj_to_other_segments(o)
return o
def stm_allocate_old_refs(n):
o = lib._stm_allocate_old(HDR + n * WORD)
tid = 421420 + n
lib._set_type_id(o, tid)
- lib._push_obj_to_other_segments(o)
return o
def stm_allocate(size):
More information about the pypy-commit
mailing list