[pypy-commit] pypy stmgc-c7: import stmgc/035e1c7879be (from branch "marker")

arigo noreply at buildbot.pypy.org
Sat Apr 19 14:05:59 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r70767:89b063cce2ab
Date: 2014-04-19 12:39 +0200
http://bitbucket.org/pypy/pypy/changeset/89b063cce2ab/

Log:	import stmgc/035e1c7879be (from branch "marker")

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 @@
-918b1901b1f9
+035e1c7879be
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
@@ -621,6 +621,9 @@
                        (int)pseg->transaction_state);
     }
 
+    /* look up and preserve the marker information as a string */
+    marker_fetch_expand(pseg);
+
     /* throw away the content of the nursery */
     long bytes_in_nursery = throw_away_nursery(pseg);
 
@@ -631,6 +634,7 @@
        value before the transaction start */
     stm_thread_local_t *tl = pseg->pub.running_thread;
     assert(tl->shadowstack >= pseg->shadowstack_at_start_of_transaction);
+    pseg->shadowstack_at_abort = tl->shadowstack;
     tl->shadowstack = pseg->shadowstack_at_start_of_transaction;
     tl->thread_local_obj = pseg->threadlocal_at_start_of_transaction;
     tl->last_abort__bytes_in_nursery = bytes_in_nursery;
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
@@ -153,11 +153,15 @@
        'thread_local_obj' field. */
     struct stm_shadowentry_s *shadowstack_at_start_of_transaction;
     object_t *threadlocal_at_start_of_transaction;
+    struct stm_shadowentry_s *shadowstack_at_abort;
 
     /* For debugging */
 #ifndef NDEBUG
     pthread_t running_pthread;
 #endif
+
+    /* Temporarily stores the marker information */
+    char marker_self[_STM_MARKER_LEN];
 };
 
 enum /* safe_point */ {
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
@@ -380,7 +380,7 @@
         struct stm_shadowentry_s *current = tl->shadowstack;
         struct stm_shadowentry_s *base = tl->shadowstack_base;
         while (current-- != base) {
-            if (((uintptr_t)current->ss) > STM_STACK_MARKER_OLD)
+            if ((((uintptr_t)current->ss) & 3) == 0)
                 mark_visit_object(current->ss, segment_base);
         }
         mark_visit_object(tl->thread_local_obj, segment_base);
diff --git a/rpython/translator/stm/src_stm/stm/marker.c b/rpython/translator/stm/src_stm/stm/marker.c
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/marker.c
@@ -0,0 +1,65 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+
+void (*stmcb_expand_marker)(uintptr_t odd_number,
+                            object_t *following_object,
+                            char *outputbuf, size_t outputbufsize);
+
+
+static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg)
+{
+    if (pseg->marker_self[0] != 0)
+        return;   /* already collected an entry */
+
+    if (stmcb_expand_marker != NULL) {
+        stm_thread_local_t *tl = pseg->pub.running_thread;
+        struct stm_shadowentry_s *current = tl->shadowstack - 1;
+        struct stm_shadowentry_s *base = tl->shadowstack_base;
+        while (--current >= base) {
+            uintptr_t x = (uintptr_t)current->ss;
+            if (x & 1) {
+                /* the stack entry is an odd number */
+                stmcb_expand_marker(x, current[1].ss,
+                                    pseg->marker_self, _STM_MARKER_LEN);
+
+                if (pseg->marker_self[0] == 0) {
+                    pseg->marker_self[0] = '?';
+                    pseg->marker_self[1] = 0;
+                }
+                break;
+            }
+        }
+    }
+}
+
+char *_stm_expand_marker(void)
+{
+    struct stm_priv_segment_info_s *pseg =
+        get_priv_segment(STM_SEGMENT->segment_num);
+    pseg->marker_self[0] = 0;
+    marker_fetch_expand(pseg);
+    return pseg->marker_self;
+}
+
+static void marker_copy(stm_thread_local_t *tl,
+                        struct stm_priv_segment_info_s *pseg,
+                        enum stm_time_e attribute_to, double time)
+{
+    /* Copies the marker information from pseg to tl.  This is called
+       indirectly from abort_with_mutex(), but only if the lost time is
+       greater than that of the previous recorded marker.  By contrast,
+       pseg->marker_self has been filled already in all cases.  The
+       reason for the two steps is that we must fill pseg->marker_self
+       earlier than now (some objects may be GCed), but we only know
+       here the total time it gets attributed.
+    */
+    if (time * 0.99 > tl->longest_marker_time) {
+        tl->longest_marker_state = attribute_to;
+        tl->longest_marker_time = time;
+        memcpy(tl->longest_marker_self, pseg->marker_self, _STM_MARKER_LEN);
+    }
+    pseg->marker_self[0] = 0;
+}
diff --git a/rpython/translator/stm/src_stm/stm/marker.h b/rpython/translator/stm/src_stm/stm/marker.h
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/marker.h
@@ -0,0 +1,6 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+
+static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg);
+static void marker_copy(stm_thread_local_t *tl,
+                        struct stm_priv_segment_info_s *pseg,
+                        enum stm_time_e attribute_to, double time);
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
@@ -161,28 +161,26 @@
         --current;
         OPT_ASSERT(current >= base);
 
-        switch ((uintptr_t)current->ss) {
+        uintptr_t x = (uintptr_t)current->ss;
 
-        case 0:   /* NULL */
-            continue;
-
-        case STM_STACK_MARKER_NEW:
+        if ((x & 3) == 0) {
+            /* the stack entry is a regular pointer (possibly NULL) */
+            minor_trace_if_young(&current->ss);
+        }
+        else if (x == STM_STACK_MARKER_NEW) {
             /* the marker was not already seen: mark it as seen,
                but continue looking more deeply in the shadowstack */
             current->ss = (object_t *)STM_STACK_MARKER_OLD;
-            continue;
-
-        case STM_STACK_MARKER_OLD:
+        }
+        else if (x == STM_STACK_MARKER_OLD) {
             /* the marker was already seen: we can stop the
                root stack tracing at this point */
-            goto interrupt;
-
-        default:
-            /* the stack entry is a regular pointer */
-            minor_trace_if_young(&current->ss);
+            break;
+        }
+        else {
+            /* it is an odd-valued marker, ignore */
         }
     }
- interrupt:
     minor_trace_if_young(&tl->thread_local_obj);
 }
 
diff --git a/rpython/translator/stm/src_stm/stm/timing.c b/rpython/translator/stm/src_stm/stm/timing.c
--- a/rpython/translator/stm/src_stm/stm/timing.c
+++ b/rpython/translator/stm/src_stm/stm/timing.c
@@ -36,8 +36,15 @@
 {
     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]);
+    double time_this_transaction = tl->timing[STM_TIME_RUN_CURRENT];
+    add_timing(tl, attribute_to, time_this_transaction);
     tl->timing[STM_TIME_RUN_CURRENT] = 0.0f;
+
+    if (attribute_to != STM_TIME_RUN_COMMITTED) {
+        struct stm_priv_segment_info_s *pseg =
+            get_priv_segment(STM_SEGMENT->segment_num);
+        marker_copy(tl, pseg, attribute_to, time_this_transaction);
+    }
 }
 
 static const char *timer_names[] = {
@@ -74,6 +81,10 @@
             fprintf(stderr, "    %-24s %9u %8.3f s\n",
                     timer_names[i], tl->events[i], (double)tl->timing[i]);
         }
+        fprintf(stderr, "    %-24s %6s %11.6f s\n",
+                "longest recorded marker", "", tl->longest_marker_time);
+        fprintf(stderr, "    \"%.*s\"\n",
+                (int)_STM_MARKER_LEN, tl->longest_marker_self);
         s_mutex_unlock();
     }
 }
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
@@ -15,6 +15,7 @@
 #include "stm/fprintcolor.h"
 #include "stm/weakref.h"
 #include "stm/timing.h"
+#include "stm/marker.h"
 
 #include "stm/misc.c"
 #include "stm/list.c"
@@ -34,3 +35,4 @@
 #include "stm/fprintcolor.c"
 #include "stm/weakref.c"
 #include "stm/timing.c"
+#include "stm/marker.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
@@ -74,6 +74,8 @@
     _STM_TIME_N
 };
 
+#define _STM_MARKER_LEN  80
+
 typedef struct stm_thread_local_s {
     /* every thread should handle the shadow stack itself */
     struct stm_shadowentry_s *shadowstack, *shadowstack_base;
@@ -91,6 +93,11 @@
     float timing[_STM_TIME_N];
     double _timing_cur_start;
     enum stm_time_e _timing_cur_state;
+    /* the marker with the longest associated time so far */
+    enum stm_time_e longest_marker_state;
+    double longest_marker_time;
+    char longest_marker_self[_STM_MARKER_LEN];
+    char longest_marker_other[_STM_MARKER_LEN];
     /* the next fields are handled internally by the library */
     int associated_segment_num;
     struct stm_thread_local_s *prev, *next;
@@ -265,8 +272,8 @@
 #define STM_PUSH_ROOT(tl, p)   ((tl).shadowstack++->ss = (object_t *)(p))
 #define STM_POP_ROOT(tl, p)    ((p) = (typeof(p))((--(tl).shadowstack)->ss))
 #define STM_POP_ROOT_RET(tl)   ((--(tl).shadowstack)->ss)
-#define STM_STACK_MARKER_NEW   1
-#define STM_STACK_MARKER_OLD   2
+#define STM_STACK_MARKER_NEW   2
+#define STM_STACK_MARKER_OLD   6
 
 
 /* Every thread needs to have a corresponding stm_thread_local_t
@@ -369,6 +376,41 @@
 void stm_flush_timing(stm_thread_local_t *tl, int verbose);
 
 
+/* The markers pushed in the shadowstack are an odd number followed by a
+   regular pointer.  When needed, this library invokes this callback to
+   turn this pair into a human-readable explanation. */
+extern void (*stmcb_expand_marker)(uintptr_t odd_number,
+                                   object_t *following_object,
+                                   char *outputbuf, size_t outputbufsize);
+
+/* Conventience macros to push the markers into the shadowstack */
+#define STM_PUSH_MARKER(tl, odd_num, p)   do {  \
+    uintptr_t _odd_num = (odd_num);             \
+    assert(_odd_num & 1);                       \
+    STM_PUSH_ROOT(tl, _odd_num);                \
+    STM_PUSH_ROOT(tl, p);                       \
+} while (0)
+
+#define STM_POP_MARKER(tl)   ({                 \
+    object_t *_popped = STM_POP_ROOT_RET(tl);   \
+    STM_POP_ROOT_RET(tl);                       \
+    _popped;                                    \
+})
+
+#define STM_UPDATE_MARKER_NUM(tl, odd_num)  do {                \
+    uintptr_t _odd_num = (odd_num);                             \
+    assert(_odd_num & 1);                                       \
+    struct stm_shadowentry_s *_ss = (tl).shadowstack - 2;       \
+    while (!(((uintptr_t)(_ss->ss)) & 1)) {                     \
+        _ss--;                                                  \
+        assert(_ss >= (tl).shadowstack_base);                   \
+    }                                                           \
+    _ss->ss = (object_t *)_odd_num;                             \
+} while (0)
+
+char *_stm_expand_marker(void);
+
+
 /* ==================== END ==================== */
 
 #endif


More information about the pypy-commit mailing list