Author: Armin Rigo <[email protected]>
Branch: stmgc-c7
Changeset: r70337:720e8ae12d2f
Date: 2014-03-30 21:26 +0200
http://bitbucket.org/pypy/pypy/changeset/720e8ae12d2f/

Log:    import stmgc/976a1d42a508

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 @@
-4d330c8e6b92
+976a1d42a508
diff --git a/rpython/translator/stm/src_stm/stm/contention.c 
b/rpython/translator/stm/src_stm/stm/contention.c
--- a/rpython/translator/stm/src_stm/stm/contention.c
+++ b/rpython/translator/stm/src_stm/stm/contention.c
@@ -123,8 +123,8 @@
 #endif
 
     /* Fix the choices that are found incorrect due to TS_INEVITABLE
-       or NSE_SIGABORT */
-    if (contmgr.other_pseg->pub.nursery_end == NSE_SIGABORT) {
+       or is_abort() */
+    if (is_abort(contmgr.other_pseg->pub.nursery_end)) {
         contmgr.abort_other = true;
         contmgr.try_sleep = false;
     }
@@ -137,6 +137,19 @@
         contmgr.abort_other = false;
     }
 
+
+    int wait_category =
+        kind == WRITE_READ_CONTENTION ? STM_TIME_WAIT_WRITE_READ :
+        kind == INEVITABLE_CONTENTION ? STM_TIME_WAIT_INEVITABLE :
+        STM_TIME_WAIT_OTHER;
+
+    int abort_category =
+        kind == WRITE_WRITE_CONTENTION ? STM_TIME_RUN_ABORTED_WRITE_WRITE :
+        kind == WRITE_READ_CONTENTION ? STM_TIME_RUN_ABORTED_WRITE_READ :
+        kind == INEVITABLE_CONTENTION ? STM_TIME_RUN_ABORTED_INEVITABLE :
+        STM_TIME_RUN_ABORTED_OTHER;
+
+
     if (contmgr.try_sleep && kind != WRITE_WRITE_CONTENTION &&
         contmgr.other_pseg->safe_point != SP_WAIT_FOR_C_TRANSACTION_DONE) {
         /* Sleep.
@@ -150,6 +163,10 @@
         */
         contmgr.other_pseg->signal_when_done = true;
 
+        change_timing_state(wait_category);
+
+        /* XXX should also tell other_pseg "please commit soon" */
+
         dprintf(("pausing...\n"));
         cond_signal(C_AT_SAFE_POINT);
         STM_PSEGMENT->safe_point = SP_WAIT_FOR_C_TRANSACTION_DONE;
@@ -159,15 +176,20 @@
 
         if (must_abort())
             abort_with_mutex();
+
+        change_timing_state(STM_TIME_RUN_CURRENT);
     }
+
     else if (!contmgr.abort_other) {
         dprintf(("abort in contention\n"));
+        STM_SEGMENT->nursery_end = abort_category;
         abort_with_mutex();
     }
+
     else {
         /* We have to signal the other thread to abort, and wait until
            it does. */
-        contmgr.other_pseg->pub.nursery_end = NSE_SIGABORT;
+        contmgr.other_pseg->pub.nursery_end = abort_category;
 
         int sp = contmgr.other_pseg->safe_point;
         switch (sp) {
diff --git a/rpython/translator/stm/src_stm/stm/contention.h 
b/rpython/translator/stm/src_stm/stm/contention.h
--- a/rpython/translator/stm/src_stm/stm/contention.h
+++ b/rpython/translator/stm/src_stm/stm/contention.h
@@ -4,7 +4,11 @@
 static void write_read_contention_management(uint8_t other_segment_num);
 static void inevitable_contention_management(uint8_t other_segment_num);
 
+static inline bool is_abort(uintptr_t nursery_end) {
+    return (nursery_end <= _STM_NSE_SIGNAL_MAX && nursery_end != NSE_SIGPAUSE);
+}
+
 static inline bool is_aborting_now(uint8_t other_segment_num) {
-    return (get_segment(other_segment_num)->nursery_end == NSE_SIGABORT &&
+    return (is_abort(get_segment(other_segment_num)->nursery_end) &&
             get_priv_segment(other_segment_num)->safe_point != SP_RUNNING);
 }
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
@@ -173,7 +173,7 @@
 
   retry:
     if (jmpbuf == NULL) {
-        wait_for_end_of_inevitable_transaction(false);
+        wait_for_end_of_inevitable_transaction(tl);
     }
 
     if (!acquire_thread_segment(tl))
@@ -182,6 +182,8 @@
 
     assert(STM_PSEGMENT->safe_point == SP_NO_TRANSACTION);
     assert(STM_PSEGMENT->transaction_state == TS_NONE);
+    change_timing_state(STM_TIME_RUN_CURRENT);
+    STM_PSEGMENT->start_time = tl->_timing_cur_start;
     STM_PSEGMENT->safe_point = SP_RUNNING;
     STM_PSEGMENT->transaction_state = (jmpbuf != NULL ? TS_REGULAR
                                                       : TS_INEVITABLE);
@@ -434,7 +436,7 @@
     list_clear(STM_PSEGMENT->modified_old_objects);
 }
 
-static void _finish_transaction(void)
+static void _finish_transaction(int attribute_to)
 {
     STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
     STM_PSEGMENT->transaction_state = TS_NONE;
@@ -443,6 +445,8 @@
     LIST_FREE(STM_PSEGMENT->objects_pointing_to_nursery);
     LIST_FREE(STM_PSEGMENT->large_overflow_objects);
 
+    timing_end_transaction(attribute_to);
+
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
     release_thread_segment(tl);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
@@ -456,6 +460,9 @@
 
     minor_collection(/*commit=*/ true);
 
+    /* the call to minor_collection() above leaves us with
+       STM_TIME_BOOKKEEPING */
+
     s_mutex_lock();
 
  restart:
@@ -506,7 +513,7 @@
     }
 
     /* done */
-    _finish_transaction();
+    _finish_transaction(STM_TIME_RUN_COMMITTED);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     s_mutex_unlock();
@@ -630,13 +637,16 @@
     /* invoke the callbacks */
     invoke_and_clear_callbacks_on_abort();
 
-    if (STM_SEGMENT->nursery_end == NSE_SIGABORT) {
+    int attribute_to = STM_TIME_RUN_ABORTED_OTHER;
+
+    if (is_abort(STM_SEGMENT->nursery_end)) {
         /* done aborting */
+        attribute_to = STM_SEGMENT->nursery_end;
         STM_SEGMENT->nursery_end = pause_signalled ? NSE_SIGPAUSE
                                                    : NURSERY_END;
     }
 
-    _finish_transaction();
+    _finish_transaction(attribute_to);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     /* Broadcast C_ABORTED to wake up contention.c */
@@ -669,7 +679,7 @@
     if (STM_PSEGMENT->transaction_state == TS_REGULAR) {
         dprintf(("become_inevitable: %s\n", msg));
 
-        wait_for_end_of_inevitable_transaction(true);
+        wait_for_end_of_inevitable_transaction(NULL);
         STM_PSEGMENT->transaction_state = TS_INEVITABLE;
         STM_SEGMENT->jmpbuf_ptr = NULL;
         clear_callbacks_on_abort();
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
@@ -29,6 +29,8 @@
 
 #define READMARKER_START      ((FIRST_OBJECT_PAGE * 4096UL) >> 4)
 #define FIRST_READMARKER_PAGE (READMARKER_START / 4096UL)
+#define OLD_RM_START          ((END_NURSERY_PAGE * 4096UL) >> 4)
+#define FIRST_OLD_RM_PAGE     (OLD_RM_START / 4096UL)
 #define NB_READMARKER_PAGES   (FIRST_OBJECT_PAGE - FIRST_READMARKER_PAGE)
 
 #define WRITELOCK_START       ((END_NURSERY_PAGE * 4096UL) >> 4)
@@ -120,7 +122,7 @@
 
     /* Start time: to know approximately for how long a transaction has
        been running, in contention management */
-    uint64_t start_time;
+    double start_time;
 
     /* This is the number stored in the overflowed objects (a multiple of
        GCFLAG_OVERFLOW_NUMBER_bit0).  It is incremented when the
diff --git a/rpython/translator/stm/src_stm/stm/gcpage.c 
b/rpython/translator/stm/src_stm/stm/gcpage.c
--- a/rpython/translator/stm/src_stm/stm/gcpage.c
+++ b/rpython/translator/stm/src_stm/stm/gcpage.c
@@ -135,11 +135,15 @@
 
     if (is_major_collection_requested()) {   /* if still true */
 
+        int oldstate = change_timing_state(STM_TIME_MAJOR_GC);
+
         synchronize_all_threads(STOP_OTHERS_UNTIL_MUTEX_UNLOCK);
 
         if (is_major_collection_requested()) {   /* if *still* true */
             major_collection_now_at_safe_point();
         }
+
+        change_timing_state(oldstate);
     }
 
     s_mutex_unlock();
diff --git a/rpython/translator/stm/src_stm/stm/nursery.c 
b/rpython/translator/stm/src_stm/stm/nursery.c
--- a/rpython/translator/stm/src_stm/stm/nursery.c
+++ b/rpython/translator/stm/src_stm/stm/nursery.c
@@ -319,7 +319,11 @@
 
     stm_safe_point();
 
+    change_timing_state(STM_TIME_MINOR_GC);
+
     _do_minor_collection(commit);
+
+    change_timing_state(commit ? STM_TIME_BOOKKEEPING : STM_TIME_RUN_CURRENT);
 }
 
 void stm_collect(long level)
diff --git a/rpython/translator/stm/src_stm/stm/nursery.h 
b/rpython/translator/stm/src_stm/stm/nursery.h
--- a/rpython/translator/stm/src_stm/stm/nursery.h
+++ b/rpython/translator/stm/src_stm/stm/nursery.h
@@ -1,11 +1,7 @@
 /* Imported by rpython/translator/stm/import_stmgc.py */
 
 /* '_stm_nursery_section_end' is either NURSERY_END or NSE_SIGxxx */
-#define NSE_SIGPAUSE   0
-#define NSE_SIGABORT   1
-#if     NSE_SIGABORT > _STM_NSE_SIGNAL_MAX
-#  error "update _STM_NSE_SIGNAL_MAX"
-#endif
+#define NSE_SIGPAUSE   STM_TIME_WAIT_OTHER
 
 
 static uint32_t highest_overflow_number;
@@ -15,9 +11,7 @@
 static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg);
 static void major_do_minor_collections(void);
 
-static inline bool must_abort(void) {
-    return STM_SEGMENT->nursery_end == NSE_SIGABORT;
-}
+#define must_abort()   is_abort(STM_SEGMENT->nursery_end)
 
 static void assert_memset_zero(void *s, size_t n);
 
diff --git a/rpython/translator/stm/src_stm/stm/pages.c 
b/rpython/translator/stm/src_stm/stm/pages.c
--- a/rpython/translator/stm/src_stm/stm/pages.c
+++ b/rpython/translator/stm/src_stm/stm/pages.c
@@ -170,25 +170,24 @@
     increment_total_allocated(total);
 }
 
+static void pages_setup_readmarkers_for_nursery(void)
+{
+    /* The nursery page's read markers are never read, but must still
+       be writeable.  We'd like to map the pages to a general "trash
+       page"; missing one, we remap all the pages over to the same one.
+       We still keep one page *per segment* to avoid cross-CPU cache
+       conflicts.
 
-#if 0
-static bool is_fully_in_shared_pages(object_t *obj)
-{
-    uintptr_t first_page = ((uintptr_t)obj) / 4096UL;
+       (XXX no performance difference measured so far)
+    */
+    long i, j;
+    for (i = 1; i <= NB_SEGMENTS; i++) {
+        char *segment_base = get_segment_base(i);
 
-    if ((obj->stm_flags & GCFLAG_SMALL_UNIFORM) != 0)
-        return (flag_page_private[first_page] == SHARED_PAGE);
-
-    ssize_t obj_size = stmcb_size_rounded_up(
-        (struct object_s *)REAL_ADDRESS(stm_object_pages, obj));
-
-    uintptr_t last_page = (((uintptr_t)obj) + obj_size - 1) / 4096UL;
-
-    do {
-        if (flag_page_private[first_page++] != SHARED_PAGE)
-            return false;
-    } while (first_page <= last_page);
-
-    return true;
+        for (j = FIRST_READMARKER_PAGE + 1; j < FIRST_OLD_RM_PAGE; j++) {
+            remap_file_pages(segment_base + 4096 * j, 4096, 0,
+                             i * NB_PAGES + FIRST_READMARKER_PAGE, 0);
+            /* errors here ignored */
+        }
+    }
 }
-#endif
diff --git a/rpython/translator/stm/src_stm/stm/pages.h 
b/rpython/translator/stm/src_stm/stm/pages.h
--- a/rpython/translator/stm/src_stm/stm/pages.h
+++ b/rpython/translator/stm/src_stm/stm/pages.h
@@ -40,6 +40,7 @@
 static void page_privatize(uintptr_t pagenum);
 static void page_reshare(uintptr_t pagenum);
 static void _page_do_reshare(long segnum, uintptr_t pagenum);
+static void pages_setup_readmarkers_for_nursery(void);
 
 /* Note: don't ever do "mutex_pages_lock(); mutex_lock()" in that order */
 static void mutex_pages_lock(void);
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
@@ -37,6 +37,7 @@
                      (FIRST_READMARKER_PAGE - 2) * 4096UL,
                      PROT_NONE);
     }
+    pages_setup_readmarkers_for_nursery();
 }
 
 void stm_setup(void)
@@ -169,6 +170,8 @@
         num = tl->prev->associated_segment_num;
     }
     tl->thread_local_obj = NULL;
+    tl->_timing_cur_state = STM_TIME_OUTSIDE_TRANSACTION;
+    tl->_timing_cur_start = get_stm_time();
 
     /* assign numbers consecutively, but that's for tests; we could also
        assign the same number to all of them and they would get their own
diff --git a/rpython/translator/stm/src_stm/stm/sync.c 
b/rpython/translator/stm/src_stm/stm/sync.c
--- a/rpython/translator/stm/src_stm/stm/sync.c
+++ b/rpython/translator/stm/src_stm/stm/sync.c
@@ -32,7 +32,6 @@
         pthread_cond_t cond[_C_TOTAL];
         /* some additional pieces of global state follow */
         uint8_t in_use1[NB_SEGMENTS];   /* 1 if running a pthread */
-        uint64_t global_time;
     };
     char reserved[192];
 } sync_ctl __attribute__((aligned(64)));
@@ -121,13 +120,14 @@
 /************************************************************/
 
 
-static void wait_for_end_of_inevitable_transaction(bool can_abort)
+static void wait_for_end_of_inevitable_transaction(
+                        stm_thread_local_t *tl_or_null_if_can_abort)
 {
     long i;
  restart:
     for (i = 1; i <= NB_SEGMENTS; i++) {
         if (get_priv_segment(i)->transaction_state == TS_INEVITABLE) {
-            if (can_abort) {
+            if (tl_or_null_if_can_abort == NULL) {
                 /* handle this case like a contention: it will either
                    abort us (not the other thread, which is inevitable),
                    or wait for a while.  If we go past this call, then we
@@ -138,7 +138,11 @@
             else {
                 /* wait for stm_commit_transaction() to finish this
                    inevitable transaction */
+                change_timing_state_tl(tl_or_null_if_can_abort,
+                                       STM_TIME_WAIT_INEVITABLE);
                 cond_wait(C_INEVITABLE);
+                /* don't bother changing the timing state again: the caller
+                   will very soon go to STM_TIME_RUN_CURRENT */
             }
             goto restart;
         }
@@ -179,6 +183,7 @@
     }
     /* No segment available.  Wait until release_thread_segment()
        signals that one segment has been freed. */
+    change_timing_state_tl(tl, STM_TIME_WAIT_FREE_SEGMENT);
     cond_wait(C_SEGMENT_FREE);
 
     /* Return false to the caller, which will call us again */
@@ -189,7 +194,6 @@
     assert(STM_SEGMENT->segment_num == num);
     assert(STM_SEGMENT->running_thread == NULL);
     STM_SEGMENT->running_thread = tl;
-    STM_PSEGMENT->start_time = ++sync_ctl.global_time;
     return true;
 }
 
@@ -307,6 +311,10 @@
 
 static void enter_safe_point_if_requested(void)
 {
+    if (STM_SEGMENT->nursery_end == NURSERY_END)
+        return;    /* fast path: no safe point requested */
+
+    int previous_state = -1;
     assert(_seems_to_be_running_transaction());
     assert(_has_mutex());
     while (1) {
@@ -323,11 +331,18 @@
 #ifdef STM_TESTS
         abort_with_mutex();
 #endif
+        if (previous_state == -1) {
+            previous_state = change_timing_state(STM_TIME_SYNC_PAUSE);
+        }
         cond_signal(C_AT_SAFE_POINT);
         STM_PSEGMENT->safe_point = SP_WAIT_FOR_C_REQUEST_REMOVED;
         cond_wait(C_REQUEST_REMOVED);
         STM_PSEGMENT->safe_point = SP_RUNNING;
     }
+
+    if (previous_state != -1) {
+        change_timing_state(previous_state);
+    }
 }
 
 static void synchronize_all_threads(enum sync_type_e sync_type)
diff --git a/rpython/translator/stm/src_stm/stm/sync.h 
b/rpython/translator/stm/src_stm/stm/sync.h
--- a/rpython/translator/stm/src_stm/stm/sync.h
+++ b/rpython/translator/stm/src_stm/stm/sync.h
@@ -29,7 +29,7 @@
 static bool acquire_thread_segment(stm_thread_local_t *tl);
 static void release_thread_segment(stm_thread_local_t *tl);
 
-static void wait_for_end_of_inevitable_transaction(bool can_abort);
+static void wait_for_end_of_inevitable_transaction(stm_thread_local_t *);
 
 enum sync_type_e {
     STOP_OTHERS_UNTIL_MUTEX_UNLOCK,
diff --git a/rpython/translator/stm/src_stm/stm/timing.c 
b/rpython/translator/stm/src_stm/stm/timing.c
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/timing.c
@@ -0,0 +1,75 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+static inline void add_timing(stm_thread_local_t *tl, enum stm_time_e category,
+                              double elapsed)
+{
+    tl->timing[category] += elapsed;
+}
+
+#define TIMING_CHANGE(tl, newstate)                     \
+    double curtime = get_stm_time();                    \
+    double elasped = curtime - tl->_timing_cur_start;   \
+    enum stm_time_e oldstate = tl->_timing_cur_state;   \
+    add_timing(tl, oldstate, elasped);                  \
+    tl->_timing_cur_state = newstate;                   \
+    tl->_timing_cur_start = curtime
+
+static enum stm_time_e change_timing_state(enum stm_time_e newstate)
+{
+    stm_thread_local_t *tl = STM_SEGMENT->running_thread;
+    TIMING_CHANGE(tl, newstate);
+    return oldstate;
+}
+
+static void change_timing_state_tl(stm_thread_local_t *tl,
+                                   enum stm_time_e newstate)
+{
+    TIMING_CHANGE(tl, newstate);
+}
+
+static void timing_end_transaction(enum stm_time_e attribute_to)
+{
+    stm_thread_local_t *tl = STM_SEGMENT->running_thread;
+    TIMING_CHANGE(tl, STM_TIME_OUTSIDE_TRANSACTION);
+    add_timing(tl, attribute_to, tl->timing[STM_TIME_RUN_CURRENT]);
+    tl->timing[STM_TIME_RUN_CURRENT] = 0.0f;
+}
+
+static const char *timer_names[] = {
+    "outside transaction",
+    "run current",
+    "run committed",
+    "run aborted write write",
+    "run aborted write read",
+    "run aborted inevitable",
+    "run aborted other",
+    "wait free segment",
+    "wait write read",
+    "wait inevitable",
+    "wait other",
+    "bookkeeping",
+    "minor gc",
+    "major gc",
+    "sync pause",
+};
+
+void stm_flush_timing(stm_thread_local_t *tl, int verbose)
+{
+    TIMING_CHANGE(tl, tl->_timing_cur_state);
+
+    assert((sizeof(timer_names) / sizeof(timer_names[0])) == _STM_TIME_N);
+    if (verbose > 0) {
+        int i;
+        s_mutex_lock();
+        fprintf(stderr, "thread %p:\n", tl);
+        for (i = 0; i < _STM_TIME_N; i++) {
+            fprintf(stderr, "    %-24s %.3f s\n",
+                    timer_names[i], (double)tl->timing[i]);
+        }
+        s_mutex_unlock();
+    }
+}
diff --git a/rpython/translator/stm/src_stm/stm/timing.h 
b/rpython/translator/stm/src_stm/stm/timing.h
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/timing.h
@@ -0,0 +1,15 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#include <time.h>
+
+static inline double get_stm_time(void)
+{
+    struct timespec tp;
+    clock_gettime(CLOCK_MONOTONIC, &tp);
+    return tp.tv_sec + tp.tv_nsec * 0.000000001;
+}
+
+static enum stm_time_e change_timing_state(enum stm_time_e newstate);
+static void change_timing_state_tl(stm_thread_local_t *tl,
+                                   enum stm_time_e newstate);
+
+static void timing_end_transaction(enum stm_time_e attribute_to);
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
@@ -14,6 +14,7 @@
 #include "stm/extra.h"
 #include "stm/fprintcolor.h"
 #include "stm/weakref.h"
+#include "stm/timing.h"
 
 #include "stm/misc.c"
 #include "stm/list.c"
@@ -32,3 +33,4 @@
 #include "stm/extra.c"
 #include "stm/fprintcolor.c"
 #include "stm/weakref.c"
+#include "stm/timing.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
@@ -55,6 +55,25 @@
     object_t *ss;
 };
 
+enum stm_time_e {
+    STM_TIME_OUTSIDE_TRANSACTION,
+    STM_TIME_RUN_CURRENT,
+    STM_TIME_RUN_COMMITTED,
+    STM_TIME_RUN_ABORTED_WRITE_WRITE,
+    STM_TIME_RUN_ABORTED_WRITE_READ,
+    STM_TIME_RUN_ABORTED_INEVITABLE,
+    STM_TIME_RUN_ABORTED_OTHER,
+    STM_TIME_WAIT_FREE_SEGMENT,
+    STM_TIME_WAIT_WRITE_READ,
+    STM_TIME_WAIT_INEVITABLE,
+    STM_TIME_WAIT_OTHER,
+    STM_TIME_BOOKKEEPING,
+    STM_TIME_MINOR_GC,
+    STM_TIME_MAJOR_GC,
+    STM_TIME_SYNC_PAUSE,
+    _STM_TIME_N
+};
+
 typedef struct stm_thread_local_s {
     /* every thread should handle the shadow stack itself */
     struct stm_shadowentry_s *shadowstack, *shadowstack_base;
@@ -67,6 +86,10 @@
     /* after an abort, some details about the abort are stored there.
        (these fields are not modified on a successful commit) */
     long last_abort__bytes_in_nursery;
+    /* timing information, accumulated */
+    float timing[_STM_TIME_N];
+    double _timing_cur_start;
+    enum stm_time_e _timing_cur_state;
     /* the next fields are handled internally by the library */
     int associated_segment_num;
     struct stm_thread_local_s *prev, *next;
@@ -114,7 +137,7 @@
 #endif
 
 #define _STM_GCFLAG_WRITE_BARRIER      0x01
-#define _STM_NSE_SIGNAL_MAX               1
+#define _STM_NSE_SIGNAL_MAX     _STM_TIME_N
 #define _STM_FAST_ALLOC           (66*1024)
 
 
@@ -337,6 +360,10 @@
                                             const char *msg);
 
 
+/* Temporary? */
+void stm_flush_timing(stm_thread_local_t *tl, int verbose);
+
+
 /* ==================== END ==================== */
 
 #endif
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to