[pypy-commit] pypy stmgc-c4: Import stmgc/59eb9a85c3d1.
arigo
noreply at buildbot.pypy.org
Sun Jun 30 19:58:32 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c4
Changeset: r65124:674cdae07936
Date: 2013-06-30 19:49 +0200
http://bitbucket.org/pypy/pypy/changeset/674cdae07936/
Log: Import stmgc/59eb9a85c3d1.
diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c
--- a/rpython/translator/stm/src_stm/et.c
+++ b/rpython/translator/stm/src_stm/et.c
@@ -87,6 +87,8 @@
gcptr P = G;
revision_t v;
+ d->count_reads++;
+
restart_all:
if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
{
@@ -902,6 +904,15 @@
d->reads_size_limit = d->atomic ? ULONG_MAX : d->reads_size_limit_nonatomic;
}
+long stm_atomic(long delta)
+{
+ struct tx_descriptor *d = thread_descriptor;
+ d->atomic += delta;
+ assert(d->atomic >= 0);
+ update_reads_size_limit(d);
+ return d->atomic;
+}
+
static void init_transaction(struct tx_descriptor *d)
{
assert(d->active == 0);
diff --git a/rpython/translator/stm/src_stm/gcpage.c b/rpython/translator/stm/src_stm/gcpage.c
--- a/rpython/translator/stm/src_stm/gcpage.c
+++ b/rpython/translator/stm/src_stm/gcpage.c
@@ -321,13 +321,20 @@
static void mark_roots(gcptr *root, gcptr *end)
{
- //assert(*root == END_MARKER);
- //root++;
+ assert(*root == END_MARKER_ON);
+ root++;
+
while (root != end) {
- gcptr o = *root;
- visit(root);
- dprintf(("visit stack root: %p -> %p\n", o, *root));
- (void)o; /* silence "warning: unused variable 'o'" */
+ gcptr item = *root;
+ if (((revision_t)item) & ~((revision_t)END_MARKER_OFF |
+ (revision_t)END_MARKER_ON)) {
+ /* 'item' is a regular, non-null pointer */
+ visit(root);
+ dprintf(("visit stack root: %p -> %p\n", item, *root));
+ }
+ else if (item == END_MARKER_OFF) {
+ *root = END_MARKER_ON;
+ }
root++;
}
}
diff --git a/rpython/translator/stm/src_stm/nursery.c b/rpython/translator/stm/src_stm/nursery.c
--- a/rpython/translator/stm/src_stm/nursery.c
+++ b/rpython/translator/stm/src_stm/nursery.c
@@ -324,12 +324,30 @@
static void mark_young_roots(struct tx_descriptor *d)
{
- gcptr *root = d->shadowstack;
+ /* we walk the shadowstack from the end, replacing any END_MARKER_OFF
+ found with END_MARKER_ON. When we reach an END_MARKER_ON, we know
+ that we have already seen the rest of the stack in the previous
+ nursery collection, so we stop.
+ */
gcptr *end = *d->shadowstack_end_ref;
- /* XXX use a way to avoid walking all roots again and again */
- for (; root != end; root++) {
- visit_if_young(root);
+ while (1) {
+ assert(end > d->shadowstack);
+ gcptr item = *--end;
+
+ if (((revision_t)item) & ~((revision_t)END_MARKER_OFF |
+ (revision_t)END_MARKER_ON)) {
+ /* 'item' is a regular, non-null pointer */
+ visit_if_young(end);
+ }
+ else if (item != NULL) {
+ if (item == END_MARKER_OFF)
+ *end = END_MARKER_ON;
+ else {
+ assert(item == END_MARKER_ON);
+ break;
+ }
+ }
}
}
diff --git a/rpython/translator/stm/src_stm/nursery.h b/rpython/translator/stm/src_stm/nursery.h
--- a/rpython/translator/stm/src_stm/nursery.h
+++ b/rpython/translator/stm/src_stm/nursery.h
@@ -19,6 +19,9 @@
# error "GC_NURSERY must be a multiple of GC_NURSERY_SECTION"
#endif
+#define END_MARKER_OFF ((gcptr) 16)
+#define END_MARKER_ON ((gcptr) 24)
+
#define NURSERY_FIELDS_DECL \
/* the nursery */ \
diff --git a/rpython/translator/stm/src_stm/revision b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-1ba74b051c7b
+59eb9a85c3d1
diff --git a/rpython/translator/stm/src_stm/stmgc.h b/rpython/translator/stm/src_stm/stmgc.h
--- a/rpython/translator/stm/src_stm/stmgc.h
+++ b/rpython/translator/stm/src_stm/stmgc.h
@@ -58,7 +58,8 @@
/* start a new transaction, calls callback(), and when it returns
finish that transaction. callback() is called with the 'arg'
provided, and with a retry_counter number. Must save roots around
- this call. */
+ this call. The callback() is called repeatedly as long as it
+ returns a value > 0. */
void stm_perform_transaction(gcptr arg, int (*callback)(gcptr, int));
/* finish the current transaction, start a new one, or turn the current
@@ -71,8 +72,18 @@
/* debugging: check if we're currently running a transaction or not. */
int stm_in_transaction(void);
-/* change the default transaction length */
+/* change the default transaction length, and ask if now would be a good
+ time to break the transaction (by returning from the 'callback' above
+ with a positive value). */
void stm_set_transaction_length(long length_max);
+_Bool stm_should_break_transaction(void);
+
+/* change the atomic counter by 'delta' and return the new value. Used
+ with +1 to enter or with -1 to leave atomic mode, or with 0 to just
+ know the current value of the counter. The current transaction is
+ *never* interrupted as long as this counter is positive. */
+long stm_atomic(long delta);
+
/* callback: get the size of an object */
extern size_t stmcb_size(gcptr);
diff --git a/rpython/translator/stm/src_stm/stmsync.c b/rpython/translator/stm/src_stm/stmsync.c
--- a/rpython/translator/stm/src_stm/stmsync.c
+++ b/rpython/translator/stm/src_stm/stmsync.c
@@ -7,6 +7,7 @@
__thread gcptr *stm_shadowstack;
static unsigned long stm_regular_length_limit = 10000;
+static revision_t sync_required = 0;
void stm_set_transaction_length(long length_max)
{
@@ -17,6 +18,38 @@
stm_regular_length_limit = length_max;
}
+_Bool stm_should_break_transaction(void)
+{
+ struct tx_descriptor *d = thread_descriptor;
+
+ /* a single comparison to handle all cases:
+
+ - first, if sync_required == -1, this should return True.
+
+ - if d->atomic, then we should return False. This is done by
+ forcing reads_size_limit to ULONG_MAX as soon as atomic > 0.
+
+ - otherwise, if is_inevitable(), then we should return True.
+ This is done by forcing both reads_size_limit and
+ reads_size_limit_nonatomic to 0 in that case.
+
+ - finally, the default case: return True if d->count_reads is
+ greater than reads_size_limit == reads_size_limit_nonatomic.
+ */
+#ifdef _GC_DEBUG
+ /* reads_size_limit is ULONG_MAX if d->atomic, or else it is equal to
+ reads_size_limit_nonatomic. */
+ assert(d->reads_size_limit == (d->atomic ? ULONG_MAX :
+ d->reads_size_limit_nonatomic));
+ /* if is_inevitable(), reads_size_limit_nonatomic should be 0
+ (and thus reads_size_limit too, if !d->atomic.) */
+ if (d->active == 2)
+ assert(d->reads_size_limit_nonatomic == 0);
+#endif
+
+ return (sync_required | d->count_reads) >= d->reads_size_limit;
+}
+
static void init_shadowstack(void)
{
struct tx_descriptor *d = thread_descriptor;
@@ -26,14 +59,14 @@
}
stm_shadowstack = d->shadowstack;
d->shadowstack_end_ref = &stm_shadowstack;
- //stm_push_root(END_MARKER);
+ stm_push_root(END_MARKER_ON);
}
static void done_shadowstack(void)
{
struct tx_descriptor *d = thread_descriptor;
- //gcptr x = stm_pop_root();
- //assert(x == END_MARKER);
+ gcptr x = stm_pop_root();
+ assert(x == END_MARKER_ON);
assert(stm_shadowstack == d->shadowstack);
stm_shadowstack = NULL;
free(d->shadowstack);
@@ -68,8 +101,6 @@
/************************************************************/
-static revision_t sync_required = 0;
-
void stm_perform_transaction(gcptr arg, int (*callback)(gcptr, int))
{ /* must save roots around this call */
jmp_buf _jmpbuf;
@@ -78,6 +109,7 @@
long volatile v_atomic;
stm_push_root(arg);
+ stm_push_root(END_MARKER_OFF);
if (!(v_atomic = thread_descriptor->atomic))
CommitTransaction();
@@ -99,14 +131,7 @@
long counter, result;
counter = v_counter;
d->atomic = v_atomic;
- stm_shadowstack = v_saved_value + 1; /* skip the 'arg', pushed above */
- // if (!d->atomic) {
- // /* In non-atomic mode, we are now between two transactions.
- // It means that in the next transaction's collections we know
- // that we won't need to access the shadow stack beyond its
- // current position. So we add an end marker. */
- // stm_push_root(END_MARKER);
- // }
+ stm_shadowstack = v_saved_value + 2; /*skip the two values pushed above*/
do {
v_counter = counter + 1;
@@ -136,7 +161,7 @@
/* invoke the callback in the new transaction */
arg = v_saved_value[0];
result = callback(arg, counter);
- assert(stm_shadowstack == v_saved_value + 1);
+ assert(stm_shadowstack == v_saved_value + 2);
v_atomic = d->atomic;
if (!d->atomic)
@@ -155,7 +180,9 @@
BeginInevitableTransaction();
}
- stm_pop_root(); /* pop the 'arg' */
+ gcptr x = stm_pop_root(); /* pop the END_MARKER */
+ assert(x == END_MARKER_OFF || x == END_MARKER_ON);
+ stm_pop_root(); /* pop the 'arg' */
assert(stm_shadowstack == v_saved_value);
}
@@ -240,7 +267,7 @@
which prevents any other thread from running in a transaction.
Warning, may block waiting for rwlock_in_transaction while another
thread runs a major GC itself! */
- ACCESS_ONCE(sync_required) = 1;
+ ACCESS_ONCE(sync_required) = -1;
stm_stop_sharedlock();
start_exclusivelock();
ACCESS_ONCE(sync_required) = 0;
More information about the pypy-commit
mailing list