[pypy-commit] pypy stmgc-c7: import stmgc/1d2c771f29c4
arigo
noreply at buildbot.pypy.org
Tue Aug 19 19:05:55 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r72911:adc9972b698b
Date: 2014-08-19 17:30 +0200
http://bitbucket.org/pypy/pypy/changeset/adc9972b698b/
Log: import stmgc/1d2c771f29c4
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 @@
-e85ce411f190
+1d2c771f29c4
diff --git a/rpython/translator/stm/src_stm/stm/core.c b/rpython/translator/stm/src_stm/stm/core.c
--- a/rpython/translator/stm/src_stm/stm/core.c
+++ b/rpython/translator/stm/src_stm/stm/core.c
@@ -376,7 +376,8 @@
assert(list_is_empty(STM_PSEGMENT->young_weakrefs));
assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery));
assert(tree_is_cleared(STM_PSEGMENT->nursery_objects_shadows));
- assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_abort));
+ assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_commit_and_abort[0]));
+ assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_commit_and_abort[1]));
assert(STM_PSEGMENT->objects_pointing_to_nursery == NULL);
assert(STM_PSEGMENT->large_overflow_objects == NULL);
#ifndef NDEBUG
@@ -851,7 +852,7 @@
STM_PSEGMENT->overflow_number_has_been_used = false;
}
- clear_callbacks_on_abort();
+ invoke_and_clear_user_callbacks(0); /* for commit */
/* send what is hopefully the correct signals */
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
@@ -1045,7 +1046,7 @@
memset(tl->mem_clear_on_abort, 0, tl->mem_bytes_to_clear_on_abort);
/* invoke the callbacks */
- invoke_and_clear_callbacks_on_abort();
+ invoke_and_clear_user_callbacks(1); /* for abort */
int attribute_to = STM_TIME_RUN_ABORTED_OTHER;
@@ -1102,7 +1103,7 @@
wait_for_end_of_inevitable_transaction(NULL);
STM_PSEGMENT->transaction_state = TS_INEVITABLE;
stm_rewind_jmp_forget(STM_SEGMENT->running_thread);
- clear_callbacks_on_abort();
+ invoke_and_clear_user_callbacks(0); /* for commit */
}
else {
assert(STM_PSEGMENT->transaction_state == TS_INEVITABLE);
diff --git a/rpython/translator/stm/src_stm/stm/core.h b/rpython/translator/stm/src_stm/stm/core.h
--- a/rpython/translator/stm/src_stm/stm/core.h
+++ b/rpython/translator/stm/src_stm/stm/core.h
@@ -133,8 +133,9 @@
weakrefs never point to young objects and never contain NULL. */
struct list_s *old_weakrefs;
- /* Tree of 'key->callback' associations from stm_call_on_abort() */
- struct tree_s *callbacks_on_abort;
+ /* Tree of 'key->callback' associations from stm_call_on_commit()
+ and stm_call_on_abort() (respectively, array items 0 and 1) */
+ struct tree_s *callbacks_on_commit_and_abort[2];
/* Start time: to know approximately for how long a transaction has
been running, in contention management */
diff --git a/rpython/translator/stm/src_stm/stm/extra.c b/rpython/translator/stm/src_stm/stm/extra.c
--- a/rpython/translator/stm/src_stm/stm/extra.c
+++ b/rpython/translator/stm/src_stm/stm/extra.c
@@ -4,55 +4,76 @@
#endif
-void stm_call_on_abort(stm_thread_local_t *tl,
- void *key, void callback(void *))
+static bool register_callbacks(stm_thread_local_t *tl,
+ void *key, void callback(void *), long index)
{
if (!_stm_in_transaction(tl)) {
/* check that the current thread-local is really running a
transaction, and do nothing otherwise. */
- return;
+ return false;
}
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
/* ignore callbacks if we're in an inevitable transaction
(which cannot abort) */
- return;
+ return false;
}
+ struct tree_s *callbacks;
+ callbacks = STM_PSEGMENT->callbacks_on_commit_and_abort[index];
+
if (callback == NULL) {
/* ignore the return value: unregistered keys can be
"deleted" again */
- tree_delete_item(STM_PSEGMENT->callbacks_on_abort, (uintptr_t)key);
+ tree_delete_item(callbacks, (uintptr_t)key);
}
else {
/* double-registering the same key will crash */
- tree_insert(STM_PSEGMENT->callbacks_on_abort,
- (uintptr_t)key, (uintptr_t)callback);
+ tree_insert(callbacks, (uintptr_t)key, (uintptr_t)callback);
+ }
+ return true;
+}
+
+void stm_call_on_commit(stm_thread_local_t *tl,
+ void *key, void callback(void *))
+{
+ if (!register_callbacks(tl, key, callback, 0)) {
+ /* no regular transaction running, invoke the callback
+ immediately */
+ callback(key);
}
}
-static void clear_callbacks_on_abort(void)
+void stm_call_on_abort(stm_thread_local_t *tl,
+ void *key, void callback(void *))
{
- if (!tree_is_cleared(STM_PSEGMENT->callbacks_on_abort))
- tree_clear(STM_PSEGMENT->callbacks_on_abort);
+ register_callbacks(tl, key, callback, 1);
}
-static void invoke_and_clear_callbacks_on_abort(void)
+static void invoke_and_clear_user_callbacks(long index)
{
- wlog_t *item;
- struct tree_s *callbacks = STM_PSEGMENT->callbacks_on_abort;
+ struct tree_s *callbacks;
+
+ /* clear the callbacks that we don't want to invoke at all */
+ callbacks = STM_PSEGMENT->callbacks_on_commit_and_abort[1 - index];
+ if (!tree_is_cleared(callbacks))
+ tree_clear(callbacks);
+
+ /* invoke the callbacks from the other group */
+ callbacks = STM_PSEGMENT->callbacks_on_commit_and_abort[index];
if (tree_is_cleared(callbacks))
return;
- STM_PSEGMENT->callbacks_on_abort = tree_create();
+ STM_PSEGMENT->callbacks_on_commit_and_abort[index] = tree_create();
+ wlog_t *item;
TREE_LOOP_FORWARD(*callbacks, item) {
void *key = (void *)item->addr;
void (*callback)(void *) = (void(*)(void *))item->val;
assert(key != NULL);
assert(callback != NULL);
- /* The callback may call stm_call_on_abort(key, NULL). It is
- ignored, because 'callbacks_on_abort' was cleared already. */
+ /* The callback may call stm_call_on_abort(key, NULL). It is ignored,
+ because 'callbacks_on_commit_and_abort' was cleared already. */
callback(key);
} TREE_LOOP_END;
diff --git a/rpython/translator/stm/src_stm/stm/extra.h b/rpython/translator/stm/src_stm/stm/extra.h
--- a/rpython/translator/stm/src_stm/stm/extra.h
+++ b/rpython/translator/stm/src_stm/stm/extra.h
@@ -1,4 +1,4 @@
/* Imported by rpython/translator/stm/import_stmgc.py */
-static void clear_callbacks_on_abort(void);
-static void invoke_and_clear_callbacks_on_abort(void);
+static void invoke_and_clear_user_callbacks(long index);
+/* 0 = for commit, 1 = for abort */
diff --git a/rpython/translator/stm/src_stm/stm/setup.c b/rpython/translator/stm/src_stm/stm/setup.c
--- a/rpython/translator/stm/src_stm/stm/setup.c
+++ b/rpython/translator/stm/src_stm/stm/setup.c
@@ -127,7 +127,8 @@
pr->old_weakrefs = list_create();
pr->young_outside_nursery = tree_create();
pr->nursery_objects_shadows = tree_create();
- pr->callbacks_on_abort = tree_create();
+ pr->callbacks_on_commit_and_abort[0] = tree_create();
+ pr->callbacks_on_commit_and_abort[1] = tree_create();
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * i;
highest_overflow_number = pr->overflow_number;
pr->pub.transaction_read_version = 0xff;
@@ -167,7 +168,8 @@
list_free(pr->old_weakrefs);
tree_free(pr->young_outside_nursery);
tree_free(pr->nursery_objects_shadows);
- tree_free(pr->callbacks_on_abort);
+ tree_free(pr->callbacks_on_commit_and_abort[0]);
+ tree_free(pr->callbacks_on_commit_and_abort[1]);
}
munmap(stm_object_pages, TOTAL_MEMORY);
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
@@ -417,6 +417,12 @@
Note: 'key' must be aligned to a multiple of 8 bytes. */
void stm_call_on_abort(stm_thread_local_t *, void *key, void callback(void *));
+/* If the current transaction commits later, invoke 'callback(key)'. If
+ the current transaction aborts, then the callback is forgotten. Same
+ restrictions as stm_call_on_abort(). If the transaction is or becomes
+ inevitable, 'callback(key)' is called immediately. */
+void stm_call_on_commit(stm_thread_local_t *, void *key, void callback(void *));
+
/* Similar to stm_become_inevitable(), but additionally suspend all
other threads. A very heavy-handed way to make sure that no other
More information about the pypy-commit
mailing list