[pypy-commit] stmgc default: progress
Raemi
noreply at buildbot.pypy.org
Thu Sep 4 17:31:35 CEST 2014
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch:
Changeset: r1352:6db6026fb9a6
Date: 2014-09-04 17:32 +0200
http://bitbucket.org/pypy/stmgc/changeset/6db6026fb9a6/
Log: progress
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -7,6 +7,28 @@
/* ############# signal handler ############# */
+static void bring_page_up_to_date(uintptr_t pagenum)
+{
+ /* pagecopy from somewhere readable, then update
+ all written objs from that segment */
+ long i;
+ int my_segnum = STM_SEGMENT->segment_num;
+
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ if (i == my_segnum)
+ continue;
+ if (!is_readable_page(i, first_page))
+ continue;
+
+ acquire_privatization_lock(i);
+
+ /* copy the content from there to our segment */
+ pagecopy(new_page, get_segment_base(from_segnum) + pagenum * 4096UL);
+
+ release_privatization_lock(i);
+ }
+}
+
void _signal_handler(int sig, siginfo_t *siginfo, void *context)
{
char *addr = siginfo->si_addr;
@@ -31,7 +53,7 @@
so it needs additional synchronisation.*/
pages_set_protection(segnum, pagenum, 1, PROT_READ|PROT_WRITE);
- page_privatize(pagenum);
+ bring_page_up_to_date(pagenum);
/* XXX: ... what can go wrong when we abort from inside
the signal handler? */
@@ -143,20 +165,11 @@
/* ############# STM ############# */
-void _stm_write_slowpath(object_t *obj)
+void _privatize_and_protect_other_segments(object_t *obj)
{
- assert(_seems_to_be_running_transaction());
- assert(!_is_in_nursery(obj));
- assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
+ assert(STM_PSEGMENT->privatization_lock); /* we hold it */
+ assert(obj_size < 4096); /* too lazy right now (part of the code is ready) */
- stm_read(obj);
-
- /* XXX: misses synchronisation with other write_barriers
- on same page */
- /* XXX: make backup copy */
- /* XXX: privatize pages if necessary */
-
- /* make other segments trap if accessing this object */
uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
char *realobj;
size_t obj_size;
@@ -167,24 +180,85 @@
obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
+ /* privatize pages: */
+ /* get the last page containing data from the object */
+ end_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
+ for (i = first_page; i <= end_page; i++) {
+ if (is_private_page(my_segnum, i))
+ continue;
+ page_privatize(i);
+ bring_page_up_to_date(i);
+ }
+
+ /* then PROT_NONE everyone else that doesn't have a private
+ page already */
for (i = 0; i < NB_SEGMENTS; i++) {
if (i == my_segnum)
continue;
- if (!is_readable_page(i, first_page))
+ if (!is_readable_page(i, first_page) || is_private_page(i, first_page))
continue;
- /* XXX: only do it if not already PROT_NONE */
- char *segment_base = get_segment_base(i);
+
+ acquire_privatization_lock(i);
pages_set_protection(i, first_page, end_page - first_page + 1,
PROT_NONE);
+ release_privatization_lock(i);
+
dprintf(("prot %lu, len=%lu in seg %lu\n", first_page, (end_page - first_page + 1), i));
}
+}
+void _stm_write_slowpath(object_t *obj)
+{
+ assert(_seems_to_be_running_transaction());
+ assert(!_is_in_nursery(obj));
+ assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
+
+ int my_segnum = STM_SEGMENT->segment_num;
+ uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
+ char *realobj;
+ size_t obj_size;
+
+ realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+
+ /* add to read set: */
+ stm_read(obj);
+
+ /* create backup copy: */
+ struct object_s *bk_obj = malloc(obj_size);
+ memcpy(bk_obj, realobj, obj_size);
+
+ assert(obj_size < 4096); /* too lazy right now (part of the code is ready) */
+
+ retry:
+ acquire_privatization_lock(my_segnum);
+ if (!is_readable_page(my_segnum, first_page)) {
+ release_privatization_lock(my_segnum);
+
+ bring_page_up_to_date(first_page);
+
+ spin_loop();
+ goto retry;
+ }
+ /* page is not PROT_NONE for us, we can PROT_NONE all others */
+ _privatize_and_protect_other_segments(obj);
+
+ /* remove the WRITE_BARRIER flag (could be done later, but I
+ think we find more bugs this way) */
+ obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
+
+ /* done fiddling with protection and privatization */
+ release_privatization_lock(my_segnum);
+
+ /* phew, now add the obj to the write-set and register the
+ backup copy. */
acquire_modified_objs_lock(my_segnum);
- tree_insert(STM_PSEGMENT->modified_old_objects, (uintptr_t)obj, 0);
+ tree_insert(STM_PSEGMENT->modified_old_objects,
+ (uintptr_t)obj, (uintptr_t)bk_obj);
release_modified_objs_lock(my_segnum);
+ /* also add it to the GC list for minor collections */
LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
- obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
}
static void reset_transaction_read_version(void)
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -115,30 +115,22 @@
asm("/* workaround for llvm bug */");
}
-static inline void acquire_privatization_lock(void)
+static inline void acquire_privatization_lock(int segnum)
{
- uint8_t *lock = (uint8_t *)REAL_ADDRESS(STM_SEGMENT->segment_base,
- &STM_PSEGMENT->privatization_lock);
- spinlock_acquire(*lock);
+ spinlock_acquire(get_priv_segment(segnum)->privatization_lock);
}
-static inline void release_privatization_lock(void)
+static inline void release_privatization_lock(int segnum)
{
- uint8_t *lock = (uint8_t *)REAL_ADDRESS(STM_SEGMENT->segment_base,
- &STM_PSEGMENT->privatization_lock);
- spinlock_release(*lock);
+ spinlock_release(get_priv_segment(segnum)->privatization_lock);
}
static inline void acquire_modified_objs_lock(int segnum)
{
- uint8_t *lock = (uint8_t *)REAL_ADDRESS(get_segment_base(segnum),
- &STM_PSEGMENT->modified_objs_lock);
- spinlock_acquire(*lock);
+ spinlock_acquire(get_priv_segment(segnum)->modified_objs_lock);
}
static inline void release_modified_objs_lock(int segnum)
{
- uint8_t *lock = (uint8_t *)REAL_ADDRESS(get_segment_base(segnum),
- &STM_PSEGMENT->modified_objs_lock);
- spinlock_release(*lock);
+ spinlock_release(get_priv_segment(segnum)->modified_objs_lock);
}
diff --git a/c8/stm/pages.c b/c8/stm/pages.c
--- a/c8/stm/pages.c
+++ b/c8/stm/pages.c
@@ -74,12 +74,17 @@
while (amount-->0) {
volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
&pages_readable[pagenum + amount - PAGE_FLAG_START];
+ volatile struct page_shared_s *ps2 = (volatile struct page_shared_s *)
+ &pages_privatized[pagenum + amount - PAGE_FLAG_START];
+
if (i == 0) {
- /* readable */
+ /* readable & private */
ps->by_segment |= bitmask;
+ ps2->by_segment |= bitmask;
} else {
- /* not readable (ensured in setup.c) */
+ /* not readable (ensured in setup.c), not private */
ps->by_segment &= ~bitmask;
+ ps2->by_segment &= ~bitmask;
}
}
}
@@ -87,6 +92,9 @@
static void page_privatize(uintptr_t pagenum)
{
+ /* hopefully holding the lock */
+ assert(STM_PSEGMENT->privatization_lock);
+
/* check this thread's 'pages_privatized' bit */
uint64_t bitmask = 1UL << STM_SEGMENT->segment_num;
volatile struct page_shared_s *ps = (volatile struct page_shared_s *)
@@ -96,11 +104,6 @@
return;
}
- long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
- spinlock_acquire(get_priv_segment(i)->privatization_lock);
- }
-
/* add this thread's 'pages_privatized' bit */
ps->by_segment |= bitmask;
@@ -111,18 +114,14 @@
uintptr_t pagenum_in_file = NB_PAGES * STM_SEGMENT->segment_num + pagenum;
char *new_page = stm_object_pages + pagenum_in_file * 4096UL;
d_remap_file_pages(new_page, 4096, pagenum_in_file);
-
- /* copy the content from the shared (segment 0) source */
- pagecopy(new_page, stm_object_pages + pagenum * 4096UL);
-
- for (i = NB_SEGMENTS-1; i >= 0; i--) {
- spinlock_release(get_priv_segment(i)->privatization_lock);
- }
}
static void pages_set_protection(int segnum, uintptr_t pagenum,
uintptr_t count, int prot)
{
+ /* we hopefully hold the privatization lock: */
+ assert(get_priv_segment(segnum)->privatization_lock);
+
char *addr = get_segment_base(segnum) + pagenum * 4096UL;
mprotect(addr, count * 4096UL, prot);
More information about the pypy-commit
mailing list