Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r69852:9d5940288fd5
Date: 2014-03-11 10:05 +0100
http://bitbucket.org/pypy/pypy/changeset/9d5940288fd5/
Log: import stmgc/d912ca6f0d53
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 @@
-b4a037995423
+d912ca6f0d53
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
@@ -181,6 +181,7 @@
assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
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(STM_PSEGMENT->objects_pointing_to_nursery == NULL);
assert(STM_PSEGMENT->large_overflow_objects == NULL);
@@ -379,6 +380,8 @@
STM_PSEGMENT->overflow_number_has_been_used = false;
}
+ clear_callbacks_on_abort();
+
/* send what is hopefully the correct signals */
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
/* wake up one thread in wait_for_end_of_inevitable_transaction() */
@@ -499,6 +502,14 @@
stm_jmpbuf_t *jmpbuf_ptr = STM_SEGMENT->jmpbuf_ptr;
+ /* clear memory registered on the thread-local */
+ stm_thread_local_t *tl = STM_SEGMENT->running_thread;
+ if (tl->mem_clear_on_abort)
+ memset(tl->mem_clear_on_abort, 0, tl->mem_bytes_to_clear_on_abort);
+
+ /* invoke the callbacks */
+ invoke_and_clear_callbacks_on_abort();
+
if (STM_SEGMENT->nursery_end == NSE_SIGABORT)
STM_SEGMENT->nursery_end = NURSERY_END; /* done aborting */
@@ -538,6 +549,7 @@
wait_for_end_of_inevitable_transaction(true);
STM_PSEGMENT->transaction_state = TS_INEVITABLE;
STM_SEGMENT->jmpbuf_ptr = NULL;
+ clear_callbacks_on_abort();
}
s_mutex_unlock();
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
@@ -106,6 +106,9 @@
next minor collection. */
struct tree_s *nursery_objects_shadows;
+ /* Tree of 'key->callback' associations from stm_call_on_abort() */
+ struct tree_s *callbacks_on_abort;
+
/* Start time: to know approximately for how long a transaction has
been running, in contention management */
uint64_t start_time;
diff --git a/rpython/translator/stm/src_stm/stm/extra.c
b/rpython/translator/stm/src_stm/stm/extra.c
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/extra.c
@@ -0,0 +1,56 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+void stm_call_on_abort(void *key, void callback(void *))
+{
+ assert(_running_transaction());
+
+ if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
+ /* ignore callbacks if we're in an inevitable transaction
+ (which cannot abort) */
+ return;
+ }
+
+ if (callback == NULL) {
+ /* ignore the return value: unregistered keys can be
+ "deleted" again */
+ tree_delete_item(STM_PSEGMENT->callbacks_on_abort, (uintptr_t)key);
+ }
+ else {
+ /* double-registering the same key will crash */
+ tree_insert(STM_PSEGMENT->callbacks_on_abort,
+ (uintptr_t)key, (uintptr_t)callback);
+ }
+}
+
+static void clear_callbacks_on_abort(void)
+{
+ if (!tree_is_cleared(STM_PSEGMENT->callbacks_on_abort))
+ tree_clear(STM_PSEGMENT->callbacks_on_abort);
+}
+
+static void invoke_and_clear_callbacks_on_abort(void)
+{
+ wlog_t *item;
+ struct tree_s *callbacks = STM_PSEGMENT->callbacks_on_abort;
+ if (tree_is_cleared(callbacks))
+ return;
+ STM_PSEGMENT->callbacks_on_abort = tree_create();
+
+ 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. */
+ callback(key);
+
+ } TREE_LOOP_END;
+
+ tree_free(callbacks);
+}
diff --git a/rpython/translator/stm/src_stm/stm/extra.h
b/rpython/translator/stm/src_stm/stm/extra.h
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/extra.h
@@ -0,0 +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);
diff --git a/rpython/translator/stm/src_stm/stm/hash_id.c
b/rpython/translator/stm/src_stm/stm/hash_id.c
--- a/rpython/translator/stm/src_stm/stm/hash_id.c
+++ b/rpython/translator/stm/src_stm/stm/hash_id.c
@@ -56,7 +56,7 @@
return id_or_identityhash(obj, true);
}
-void stm_set_prebuilt_identityhash(object_t *obj, uint64_t hash)
+void stm_set_prebuilt_identityhash(object_t *obj, long hash)
{
struct object_s *realobj = (struct object_s *)
REAL_ADDRESS(stm_object_pages, obj);
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
@@ -60,6 +60,7 @@
pr->modified_old_objects = list_create();
pr->young_outside_nursery = tree_create();
pr->nursery_objects_shadows = tree_create();
+ pr->callbacks_on_abort = tree_create();
pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * (i + 1);
highest_overflow_number = pr->overflow_number;
}
@@ -97,6 +98,7 @@
list_free(pr->modified_old_objects);
tree_free(pr->young_outside_nursery);
tree_free(pr->nursery_objects_shadows);
+ tree_free(pr->callbacks_on_abort);
}
munmap(stm_object_pages, TOTAL_MEMORY);
diff --git a/rpython/translator/stm/src_stm/stmgc.c
b/rpython/translator/stm/src_stm/stmgc.c
--- a/rpython/translator/stm/src_stm/stmgc.c
+++ b/rpython/translator/stm/src_stm/stmgc.c
@@ -11,6 +11,7 @@
#include "stm/largemalloc.h"
#include "stm/nursery.h"
#include "stm/contention.h"
+#include "stm/extra.h"
#include "stm/fprintcolor.h"
#include "stm/misc.c"
@@ -26,4 +27,5 @@
#include "stm/hash_id.c"
#include "stm/core.c"
#include "stm/contention.c"
+#include "stm/extra.c"
#include "stm/fprintcolor.c"
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
@@ -54,6 +54,10 @@
object_t **shadowstack, **shadowstack_base;
/* a generic optional thread-local object */
object_t *thread_local_obj;
+ /* in case this thread runs a transaction that aborts,
+ the following raw region of memory is cleared. */
+ char *mem_clear_on_abort;
+ size_t mem_bytes_to_clear_on_abort;
/* the next fields are handled automatically by the library */
int associated_segment_num;
struct stm_thread_local_s *prev, *next;
@@ -268,12 +272,19 @@
controlled for each prebuilt object individually. (Useful uor PyPy) */
long stm_identityhash(object_t *obj);
long stm_id(object_t *obj);
-void stm_set_prebuilt_identityhash(object_t *obj, uint64_t hash);
+void stm_set_prebuilt_identityhash(object_t *obj, long hash);
/* Returns 1 if the object can still move (it's in the nursery), or 0
otherwise. After a minor collection no object can move any more. */
long stm_can_move(object_t *);
+/* If the current transaction aborts later, invoke 'callback(key)'. If
+ the current transaction commits, then the callback is forgotten. You
+ can only register one callback per key. You can call
+ 'stm_call_on_abort(key, NULL)' to cancel an existing callback.
+ Note: 'key' must be aligned to a multiple of 8 bytes. */
+void stm_call_on_abort(void *key, void callback(void *));
+
/* ==================== END ==================== */
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit