Author: Armin Rigo <[email protected]>
Branch: stmgc-c4
Changeset: r66835:157e0dd6ad13
Date: 2013-09-07 18:12 +0200
http://bitbucket.org/pypy/pypy/changeset/157e0dd6ad13/
Log: Import stmgc/4c80cba2b8ce
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
@@ -987,8 +987,12 @@
spinlock_release(d->public_descriptor->collection_lock);
/* clear memory registered by stm_clear_on_abort */
- if (stm_to_clear_on_abort)
- memset(stm_to_clear_on_abort, 0, stm_bytes_to_clear_on_abort);
+ if (d->mem_clear_on_abort)
+ memset(d->mem_clear_on_abort, 0, d->mem_bytes_to_clear_on_abort);
+
+ /* invoke the callbacks registered by stm_call_on_abort */
+ stm_invoke_callbacks_on_abort(d);
+ stm_clear_callbacks_on_abort(d);
dprintf(("\n"
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
@@ -1483,6 +1487,10 @@
d->num_commits++;
d->active = 0;
stm_stop_sharedlock();
+
+ /* clear the list of callbacks that would have been called
+ on abort */
+ stm_clear_callbacks_on_abort(d);
}
/************************************************************/
diff --git a/rpython/translator/stm/src_stm/et.h
b/rpython/translator/stm/src_stm/et.h
--- a/rpython/translator/stm/src_stm/et.h
+++ b/rpython/translator/stm/src_stm/et.h
@@ -184,6 +184,9 @@
struct tx_descriptor *tx_prev, *tx_next;
int tcolor;
pthread_t pthreadid;
+ void *mem_clear_on_abort;
+ size_t mem_bytes_to_clear_on_abort;
+ struct G2L callbacks_on_abort;
};
extern __thread struct tx_descriptor *thread_descriptor;
diff --git a/rpython/translator/stm/src_stm/extra.c
b/rpython/translator/stm/src_stm/extra.c
--- a/rpython/translator/stm/src_stm/extra.c
+++ b/rpython/translator/stm/src_stm/extra.c
@@ -15,13 +15,46 @@
}
-__thread void *stm_to_clear_on_abort = NULL;
-__thread size_t stm_bytes_to_clear_on_abort;
-
void stm_clear_on_abort(void *start, size_t bytes)
{
- stm_to_clear_on_abort = start;
- stm_bytes_to_clear_on_abort = bytes;
+ struct tx_descriptor *d = thread_descriptor;
+ assert(d != NULL);
+ d->mem_clear_on_abort = start;
+ d->mem_bytes_to_clear_on_abort = bytes;
+}
+
+void stm_call_on_abort(void *key, void callback(void *))
+{
+ struct tx_descriptor *d = thread_descriptor;
+ if (callback == NULL) {
+ /* ignore the return value: unregistered keys can be
+ "deleted" again */
+ g2l_delete_item(&d->callbacks_on_abort, (gcptr)key);
+ }
+ else {
+ /* double-registering the same key will crash */
+ g2l_insert(&d->callbacks_on_abort, (gcptr)key, (gcptr)callback);
+ }
+}
+
+void stm_clear_callbacks_on_abort(struct tx_descriptor *d)
+{
+ if (g2l_any_entry(&d->callbacks_on_abort))
+ g2l_clear(&d->callbacks_on_abort);
+}
+
+void stm_invoke_callbacks_on_abort(struct tx_descriptor *d)
+{
+ wlog_t *item;
+ G2L_LOOP_FORWARD(d->callbacks_on_abort, item) {
+ void *key = (void *)item->addr;
+ void (*callback)(void *) = (void(*)(void *))item->val;
+ assert(key != NULL);
+ assert(callback != NULL);
+
+ callback(key);
+
+ } G2L_LOOP_END;
}
diff --git a/rpython/translator/stm/src_stm/extra.h
b/rpython/translator/stm/src_stm/extra.h
--- a/rpython/translator/stm/src_stm/extra.h
+++ b/rpython/translator/stm/src_stm/extra.h
@@ -18,5 +18,7 @@
size_t stm_decode_abort_info(struct tx_descriptor *d, long long elapsed_time,
int abort_reason, struct tx_abort_info *output);
void stm_visit_abort_info(struct tx_descriptor *d, void (*visit)(gcptr *));
+void stm_clear_callbacks_on_abort(struct tx_descriptor *d);
+void stm_invoke_callbacks_on_abort(struct tx_descriptor *d);
#endif
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
@@ -208,7 +208,8 @@
//stm_dbgmem_not_used(obj, size_class * WORD, 0);
}
else {
- g2l_delete_item(&gcp->nonsmall_objects, obj);
+ int deleted = g2l_delete_item(&gcp->nonsmall_objects, obj);
+ assert(deleted);
stm_free(obj);
}
}
@@ -235,7 +236,8 @@
assert(obj->h_tid & GCFLAG_PUBLIC);
stmgcpage_acquire_global_lock();
- g2l_delete_item(®istered_stubs, obj);
+ int deleted = g2l_delete_item(®istered_stubs, obj);
+ assert(deleted);
stmgcpage_release_global_lock();
dprintf(("unregistered %p\n", obj));
}
diff --git a/rpython/translator/stm/src_stm/lists.c
b/rpython/translator/stm/src_stm/lists.c
--- a/rpython/translator/stm/src_stm/lists.c
+++ b/rpython/translator/stm/src_stm/lists.c
@@ -133,15 +133,15 @@
*(char **)p = (char *)wlog;
}
-void g2l_delete_item(struct G2L *g2l, gcptr addr)
+int g2l_delete_item(struct G2L *g2l, gcptr addr)
{
wlog_t *entry;
G2L_FIND(*g2l, addr, entry, goto missing);
entry->addr = NULL;
- return;
+ return 1;
missing:
- stm_fatalerror("g2l_delete_item: item %p not in dict", addr);
+ return 0;
}
/************************************************************/
diff --git a/rpython/translator/stm/src_stm/lists.h
b/rpython/translator/stm/src_stm/lists.h
--- a/rpython/translator/stm/src_stm/lists.h
+++ b/rpython/translator/stm/src_stm/lists.h
@@ -114,7 +114,7 @@
wlog_t *_g2l_find(char *entry, gcptr addr);
void _g2l_compress(struct G2L *g2l);
void g2l_insert(struct G2L *g2l, gcptr addr, gcptr val);
-void g2l_delete_item(struct G2L *g2l, gcptr addr);
+int g2l_delete_item(struct G2L *g2l, gcptr addr);
static inline int g2l_contains(struct G2L *g2l, gcptr addr)
{
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 @@
-24b6be3aaa67
+4c80cba2b8ce
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
@@ -176,10 +176,14 @@
/* Clear some memory when aborting a transaction in the current
thread. This is a provisional API. The information is stored
- thread-locally and belongs to the current thread. */
+ in the current tx_descriptor. */
void stm_clear_on_abort(void *start, size_t bytes);
-extern __thread void *stm_to_clear_on_abort;
-extern __thread size_t stm_bytes_to_clear_on_abort;
+
+/* 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. */
+void stm_call_on_abort(void *key, void callback(void *));
/* only user currently is stm_allocate_public_integer_address() */
void stm_register_integer_address(intptr_t);
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit