Author: Remi Meier <[email protected]>
Branch:
Changeset: r1963:6397419657be
Date: 2015-11-05 14:17 +0100
http://bitbucket.org/pypy/stmgc/changeset/6397419657be/
Log: emit DETACH/REATTACH events when detaching/reattaching an inevitable
transaction
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -100,6 +100,8 @@
#define _stm_detach_inevitable_transaction(tl) do { \
write_fence(); \
assert(_stm_detached_inevitable_from_thread == 0); \
+ if (stmcb_timing_event != NULL) \
+ {stmcb_timing_event(tl, STM_TRANSACTION_DETACH, NULL);} \
_stm_detached_inevitable_from_thread = tl->self_or_0_if_atomic; \
} while (0)
void _stm_reattach_transaction(intptr_t);
@@ -416,69 +418,6 @@
#endif
-/* Entering and leaving a "transactional code zone": a (typically very
- large) section in the code where we are running a transaction.
- This is the STM equivalent to "acquire the GIL" and "release the
- GIL", respectively. stm_read(), stm_write(), stm_allocate(), and
- other functions should only be called from within a transaction.
-
- Note that transactions, in the STM sense, cover _at least_ one
- transactional code zone. They may be longer; for example, if one
- thread does a lot of stm_enter_transactional_zone() +
- stm_become_inevitable() + stm_leave_transactional_zone(), as is
- typical in a thread that does a lot of C function calls, then we
- get only a few bigger inevitable transactions that cover the many
- short transactional zones. This is done by having
- stm_leave_transactional_zone() turn the current transaction
- inevitable and detach it from the running thread (if there is no
- other inevitable transaction running so far). Then
- stm_enter_transactional_zone() will try to reattach to it. This is
- far more efficient than constantly starting and committing
- transactions.
-
- stm_enter_transactional_zone() and stm_leave_transactional_zone()
- preserve the value of errno.
-*/
-#ifdef STM_DEBUGPRINT
-#include <stdio.h>
-#endif
-static inline void stm_enter_transactional_zone(stm_thread_local_t *tl) {
- intptr_t self = tl->self_or_0_if_atomic;
- if (__sync_bool_compare_and_swap(&_stm_detached_inevitable_from_thread,
- self, 0)) {
-#ifdef STM_DEBUGPRINT
- fprintf(stderr, "stm_enter_transactional_zone fast path\n");
-#endif
- }
- else {
- _stm_reattach_transaction(self);
- /* _stm_detached_inevitable_from_thread should be 0 here, but
- it can already have been changed from a parallel thread
- (assuming we're not inevitable ourselves) */
- }
-}
-static inline void stm_leave_transactional_zone(stm_thread_local_t *tl) {
- assert(STM_SEGMENT->running_thread == tl);
- if (stm_is_inevitable(tl)) {
-#ifdef STM_DEBUGPRINT
- fprintf(stderr, "stm_leave_transactional_zone fast path\n");
-#endif
- _stm_detach_inevitable_transaction(tl);
- }
- else {
- _stm_leave_noninevitable_transactional_zone();
- }
-}
-
-/* stm_force_transaction_break() is in theory equivalent to
- stm_leave_transactional_zone() immediately followed by
- stm_enter_transactional_zone(); however, it is supposed to be
- called in CPU-heavy threads that had a transaction run for a while,
- and so it *always* forces a commit and starts the next transaction.
- The new transaction is never inevitable. See also
- stm_should_break_transaction(). */
-void stm_force_transaction_break(stm_thread_local_t *tl);
-
/* Abort the currently running transaction. This function never
returns: it jumps back to the start of the transaction (which must
not be inevitable). */
@@ -596,6 +535,10 @@
STM_TRANSACTION_COMMIT,
STM_TRANSACTION_ABORT,
+ /* DETACH/REATTACH is used for leaving/reentering the transactional */
+ STM_TRANSACTION_DETACH,
+ STM_TRANSACTION_REATTACH,
+
/* inevitable contention: all threads that try to become inevitable
have a STM_BECOME_INEVITABLE event with a position marker. Then,
if it waits it gets a STM_WAIT_OTHER_INEVITABLE. It is possible
@@ -688,6 +631,75 @@
} while (0)
+
+/* Entering and leaving a "transactional code zone": a (typically very
+ large) section in the code where we are running a transaction.
+ This is the STM equivalent to "acquire the GIL" and "release the
+ GIL", respectively. stm_read(), stm_write(), stm_allocate(), and
+ other functions should only be called from within a transaction.
+
+ Note that transactions, in the STM sense, cover _at least_ one
+ transactional code zone. They may be longer; for example, if one
+ thread does a lot of stm_enter_transactional_zone() +
+ stm_become_inevitable() + stm_leave_transactional_zone(), as is
+ typical in a thread that does a lot of C function calls, then we
+ get only a few bigger inevitable transactions that cover the many
+ short transactional zones. This is done by having
+ stm_leave_transactional_zone() turn the current transaction
+ inevitable and detach it from the running thread (if there is no
+ other inevitable transaction running so far). Then
+ stm_enter_transactional_zone() will try to reattach to it. This is
+ far more efficient than constantly starting and committing
+ transactions.
+
+ stm_enter_transactional_zone() and stm_leave_transactional_zone()
+ preserve the value of errno.
+*/
+#ifdef STM_DEBUGPRINT
+#include <stdio.h>
+#endif
+static inline void stm_enter_transactional_zone(stm_thread_local_t *tl) {
+ intptr_t self = tl->self_or_0_if_atomic;
+ if (__sync_bool_compare_and_swap(&_stm_detached_inevitable_from_thread,
+ self, 0)) {
+ if (self != 0 && stmcb_timing_event != NULL) {
+ /* for atomic transactions, we don't emit DETACH/REATTACH */
+ stmcb_timing_event(tl, STM_TRANSACTION_REATTACH, NULL);
+ }
+#ifdef STM_DEBUGPRINT
+ fprintf(stderr, "stm_enter_transactional_zone fast path\n");
+#endif
+ }
+ else {
+ _stm_reattach_transaction(self);
+ /* _stm_detached_inevitable_from_thread should be 0 here, but
+ it can already have been changed from a parallel thread
+ (assuming we're not inevitable ourselves) */
+ }
+}
+static inline void stm_leave_transactional_zone(stm_thread_local_t *tl) {
+ assert(STM_SEGMENT->running_thread == tl);
+ if (stm_is_inevitable(tl)) {
+#ifdef STM_DEBUGPRINT
+ fprintf(stderr, "stm_leave_transactional_zone fast path\n");
+#endif
+ _stm_detach_inevitable_transaction(tl);
+ }
+ else {
+ _stm_leave_noninevitable_transactional_zone();
+ }
+}
+
+/* stm_force_transaction_break() is in theory equivalent to
+ stm_leave_transactional_zone() immediately followed by
+ stm_enter_transactional_zone(); however, it is supposed to be
+ called in CPU-heavy threads that had a transaction run for a while,
+ and so it *always* forces a commit and starts the next transaction.
+ The new transaction is never inevitable. See also
+ stm_should_break_transaction(). */
+void stm_force_transaction_break(stm_thread_local_t *tl);
+
+
/* Support for light finalizers. This is a simple version of
finalizers that guarantees not to do anything fancy, like not
resurrecting objects. */
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit