Author: Armin Rigo <[email protected]>
Branch: c7-refactor
Changeset: r830:f661c584decd
Date: 2014-02-24 16:17 +0100
http://bitbucket.org/pypy/stmgc/changeset/f661c584decd/
Log: synchronize_overflow_object_now().
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -171,6 +171,7 @@
assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
assert(STM_PSEGMENT->old_objects_pointing_to_nursery == NULL);
assert(STM_PSEGMENT->overflow_objects_pointing_to_nursery == NULL);
+ assert(STM_PSEGMENT->large_overflow_objects == NULL);
#ifdef STM_TESTS
check_nursery_at_transaction_start();
@@ -214,6 +215,60 @@
}));
}
+static void synchronize_overflow_object_now(object_t *obj)
+{
+ assert(!_is_in_nursery(obj));
+ assert((obj->stm_flags & GCFLAG_SMALL_UNIFORM) == 0);
+
+ char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ ssize_t obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+ uintptr_t start = (uintptr_t)obj;
+ uintptr_t end = start + obj_size;
+ uintptr_t first_page = start / 4096UL;
+ uintptr_t last_page = (end - 1) / 4096UL;
+
+ do {
+ if (flag_page_private[first_page] != SHARED_PAGE) {
+ /* The page is a PRIVATE_PAGE. We need to diffuse this fragment
+ of our object from our own segment to all other segments. */
+
+ 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);
+
+ long i;
+ char *src = REAL_ADDRESS(STM_SEGMENT->segment_base, start);
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ if (i != STM_SEGMENT->segment_num) {
+ char *dst = REAL_ADDRESS(get_segment_base(i), start);
+ memcpy(dst, src, copy_size);
+ }
+ }
+ }
+
+ start = (start + 4096) & ~4095;
+ } while (first_page++ < last_page);
+}
+
+static void push_overflow_objects_from_privatized_pages(void)
+{
+ if (STM_PSEGMENT->large_overflow_objects == NULL)
+ return;
+
+ LIST_FOREACH_R(STM_PSEGMENT->large_overflow_objects, object_t *,
+ synchronize_overflow_object_now(item));
+}
+
static void push_modified_to_other_segments(void)
{
long remote_num = 1 - STM_SEGMENT->segment_num;
@@ -261,6 +316,7 @@
/* reset these lists to NULL for the next transaction */
LIST_FREE(STM_PSEGMENT->old_objects_pointing_to_nursery);
LIST_FREE(STM_PSEGMENT->overflow_objects_pointing_to_nursery);
+ LIST_FREE(STM_PSEGMENT->large_overflow_objects);
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
release_thread_segment(tl);
@@ -292,7 +348,10 @@
assert(STM_PSEGMENT->transaction_state != TS_MUST_ABORT);
STM_SEGMENT->jmpbuf_ptr = NULL;
- /* copy modified object versions to other threads */
+ /* synchronize overflow objects living in privatized pages */
+ push_overflow_objects_from_privatized_pages();
+
+ /* synchronize modified old objects to other threads */
push_modified_to_other_segments();
/* update 'overflow_number' if needed */
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -82,6 +82,10 @@
collection so far. */
struct list_s *overflow_objects_pointing_to_nursery;
+ /* List of all large, overflowed objects. Only non-NULL after the
+ current transaction spanned a minor collection. */
+ struct list_s *large_overflow_objects;
+
/* Start time: to know approximately for how long a transaction has
been running, in contention management */
uint64_t start_time;
@@ -108,6 +112,9 @@
only accessed when we hold the mutex. */
uint8_t transaction_state;
+ /* Temp for minor collection */
+ bool minor_collect_will_commit_now;
+
/* In case of abort, we restore the 'shadowstack' field. */
object_t **shadowstack_at_start_of_transaction;
};
@@ -190,3 +197,5 @@
assert(!"commit: bad transaction_state");
}
}
+
+static void synchronize_overflow_object_now(object_t *obj);
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -40,7 +40,7 @@
return (lst->count == 0);
}
-static inline bool list_count(struct list_s *lst)
+static inline uintptr_t list_count(struct list_s *lst)
{
return lst->count;
}
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -53,20 +53,6 @@
#define GCWORD_MOVED ((object_t *) -42)
-static inline void minor_copy_in_page_to_other_segments(uintptr_t p,
- size_t size)
-{
- uintptr_t dataofs = (char *)p - stm_object_pages;
- assert((dataofs & 4095) + size <= 4096); /* fits in one page */
-
- if (flag_page_private[dataofs / 4096UL] != SHARED_PAGE) {
- long i;
- for (i = 1; i < NB_SEGMENTS; i++) {
- memcpy(get_segment_base(i) + dataofs, (char *)p, size);
- }
- }
-}
-
static void minor_trace_if_young(object_t **pobj)
{
/* takes a normal pointer to a thread-local pointer to an object */
@@ -104,6 +90,11 @@
/* Copy the object */
char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj);
memcpy(realnobj, realobj, size);
+
+ if (STM_PSEGMENT->minor_collect_will_commit_now)
+ synchronize_overflow_object_now(nobj);
+ else
+ LIST_APPEND(STM_PSEGMENT->large_overflow_objects, nobj);
}
else {
/* case "small enough" */
@@ -181,8 +172,11 @@
dprintf(("minor_collection commit=%d\n", (int)commit));
+ STM_PSEGMENT->minor_collect_will_commit_now = commit;
if (STM_PSEGMENT->old_objects_pointing_to_nursery == NULL)
STM_PSEGMENT->old_objects_pointing_to_nursery = list_create();
+ if (!commit && STM_PSEGMENT->large_overflow_objects == NULL)
+ STM_PSEGMENT->large_overflow_objects = list_create();
collect_roots_in_nursery();
diff --git a/c7/stm/pages.c b/c7/stm/pages.c
--- a/c7/stm/pages.c
+++ b/c7/stm/pages.c
@@ -92,6 +92,7 @@
void *localpg = stm_object_pages + localpgoff * 4096UL;
void *otherpg = stm_object_pages + otherpgoff * 4096UL;
+ memset(flag_page_private + pagenum, PRIVATE_PAGE, count);
d_remap_file_pages(localpg, count * 4096, pgoff2);
uintptr_t i;
if (full) {
@@ -104,8 +105,6 @@
if (count > 1)
pagecopy(localpg + 4096 * (count-1), otherpg + 4096 * (count-1));
}
- write_fence();
- memset(flag_page_private + pagenum, PRIVATE_PAGE, count);
}
static void _pages_privatize(uintptr_t pagenum, uintptr_t count, bool full)
@@ -143,7 +142,7 @@
}
#if 0
-static bool is_in_shared_pages(object_t *obj)
+static bool is_fully_in_shared_pages(object_t *obj)
{
uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
@@ -155,9 +154,11 @@
uintptr_t last_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
- while (first_page <= last_page)
+ do {
if (flag_page_private[first_page++] != SHARED_PAGE)
return false;
+ } while (first_page <= last_page);
+
return true;
}
#endif
diff --git a/c7/stm/pages.h b/c7/stm/pages.h
--- a/c7/stm/pages.h
+++ b/c7/stm/pages.h
@@ -7,10 +7,9 @@
physical page (the one that is within the segment 0 mmap address). */
SHARED_PAGE,
- /* Page being in the process of privatization */
- REMAPPING_PAGE,
-
- /* Page is private for each segment. */
+ /* Page is private for each segment. If we obtain this value outside
+ a mutex_pages_lock(), there might be a race: the value can say
+ PRIVATE_PAGE before the page is really un-shared. */
PRIVATE_PAGE,
};
@@ -33,4 +32,4 @@
static void mutex_pages_lock(void);
static void mutex_pages_unlock(void);
-//static bool is_in_shared_pages(object_t *obj);
+//static bool is_fully_in_shared_pages(object_t *obj); -- not needed?
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -54,6 +54,7 @@
pr->pub.segment_num = i;
pr->pub.segment_base = segment_base;
pr->overflow_objects_pointing_to_nursery = NULL;
+ pr->large_overflow_objects = NULL;
pr->modified_old_objects = list_create();
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * (i + 1);
highest_overflow_number = pr->overflow_number;
@@ -85,6 +86,7 @@
for (i = 0; i < NB_SEGMENTS; i++) {
struct stm_priv_segment_info_s *pr = get_priv_segment(i);
assert(pr->overflow_objects_pointing_to_nursery == NULL);
+ assert(pr->large_overflow_objects == NULL);
assert(pr->old_objects_pointing_to_nursery == NULL);
list_free(pr->modified_old_objects);
}
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -180,6 +180,7 @@
lpy = stm_allocate(16)
stm_set_char(lpy, 'y')
self.push_root(lpy)
+ assert modified_old_objects() == []
self.commit_transaction()
lpy = self.pop_root()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit