Author: Remi Meier <remi.me...@gmail.com>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to