[pypy-commit] pypy stmgc-c8: import stmgc (c8-marker)

arigo noreply at buildbot.pypy.org
Sun Mar 8 20:03:47 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c8
Changeset: r76284:5a3f2855c123
Date: 2015-03-08 19:54 +0100
http://bitbucket.org/pypy/pypy/changeset/5a3f2855c123/

Log:	import stmgc (c8-marker)

diff --git a/rpython/translator/stm/src_stm/extracode.h b/rpython/translator/stm/src_stm/extracode.h
--- a/rpython/translator/stm/src_stm/extracode.h
+++ b/rpython/translator/stm/src_stm/extracode.h
@@ -81,7 +81,8 @@
     return seg_base + addr + rpy_items_ofs;
 }
 
-static int _stm_expand_marker_for_pypy(stm_loc_marker_t *marker,
+static int _stm_expand_marker_for_pypy(char *segment_base,
+                                       stm_loc_marker_t *marker,
                                        char *outputbuf, int outputbufsize)
 {
     if (marker->object == NULL)
@@ -95,7 +96,6 @@
     long fnlen = 1, nlen = 1, line = 0;
     char *fn = "?", *name = "?";
 
-    char *segment_base = marker->segment_base;
     long o = (long)marker->object;
 
     co_filename    = _fetch_long(segment_base, o + g_co_filename_ofs);
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 @@
-f1272b890ba0
+e3079f525e1a
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
@@ -49,6 +49,8 @@
 
     DEBUG_EXPECT_SEGFAULT(false);
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         object_t *obj = undo->object;
         stm_char *oslice = ((stm_char *)obj) + SLICE_OFFSET(undo->slice);
         uintptr_t current_page_num = ((uintptr_t)oslice) / 4096;
@@ -228,7 +230,7 @@
         addr >= stm_object_pages+TOTAL_MEMORY) {
         /* actual segfault, unrelated to stmgc */
         fprintf(stderr, "Segmentation fault: accessing %p\n", addr);
-        raise(SIGINT);
+        abort();
     }
 
     int segnum = get_segment_of_linear_address(addr);
@@ -236,7 +238,7 @@
     if (segnum != STM_SEGMENT->segment_num) {
         fprintf(stderr, "Segmentation fault: accessing %p (seg %d) from"
                 " seg %d\n", addr, segnum, STM_SEGMENT->segment_num);
-        raise(SIGINT);
+        abort();
     }
     dprintf(("-> segment: %d\n", segnum));
 
@@ -245,7 +247,7 @@
     if (pagenum < END_NURSERY_PAGE) {
         fprintf(stderr, "Segmentation fault: accessing %p (seg %d "
                         "page %lu)\n", addr, segnum, pagenum);
-        raise(SIGINT);
+        abort();
     }
 
     DEBUG_EXPECT_SEGFAULT(false);
@@ -269,6 +271,11 @@
         struct stm_undo_s *undo = cl->written;
         struct stm_undo_s *end = undo + cl->written_count;
         for (; undo < end; undo++) {
+            if (undo->type == TYPE_POSITION_MARKER) {
+                fprintf(stderr, "    marker %p %lu\n",
+                        undo->marker_object, undo->marker_odd_number);
+                continue;
+            }
             fprintf(stderr, "    obj %p, size %d, ofs %lu: ", undo->object,
                     SLICE_SIZE(undo->slice), SLICE_OFFSET(undo->slice));
             /* long i; */
@@ -362,6 +369,8 @@
                     struct stm_undo_s *undo = cl->written;
                     struct stm_undo_s *end = cl->written + cl->written_count;
                     for (; undo < end; undo++) {
+                        if (undo->type == TYPE_POSITION_MARKER)
+                            continue;
                         if (_stm_was_read(undo->object)) {
                             /* first reset all modified objects from the backup
                                copies as soon as the first conflict is detected;
@@ -369,6 +378,7 @@
                                the old (but unmodified) version to the newer version.
                             */
                             reset_modified_from_backup_copies(my_segnum);
+                            timing_write_read_contention(cl->written, undo);
                             needs_abort = true;
 
                             dprintf(("_stm_validate() failed for obj %p\n", undo->object));
@@ -599,6 +609,8 @@
 {
     dprintf(("make_bk_slices_for_range(%p, %lu, %lu)\n",
              obj, start - (stm_char*)obj, end - start));
+    timing_record_write_position();
+
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     uintptr_t first_page = ((uintptr_t)start) / 4096UL;
     uintptr_t end_page = ((uintptr_t)end) / 4096UL;
@@ -1021,6 +1033,8 @@
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         object_t *obj = undo->object;
         obj->stm_flags &= ~GCFLAG_WB_EXECUTED;
     }
@@ -1034,6 +1048,8 @@
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         object_t *obj = undo->object;
         obj->stm_flags |= GCFLAG_WB_EXECUTED;
     }
@@ -1051,6 +1067,7 @@
 
     assert(STM_PSEGMENT->safe_point == SP_NO_TRANSACTION);
     assert(STM_PSEGMENT->transaction_state == TS_NONE);
+    timing_event(tl, STM_TRANSACTION_START);
     STM_PSEGMENT->transaction_state = TS_REGULAR;
     STM_PSEGMENT->safe_point = SP_RUNNING;
 #ifndef NDEBUG
@@ -1080,6 +1097,10 @@
     assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_commit_and_abort[1]));
     assert(list_is_empty(STM_PSEGMENT->young_objects_with_light_finalizers));
     assert(STM_PSEGMENT->finalizers == NULL);
+#ifndef NDEBUG
+    /* this should not be used when objects_pointing_to_nursery == NULL */
+    STM_PSEGMENT->position_markers_len_old = 99999999999999999L;
+#endif
 
     check_nursery_at_transaction_start();
 
@@ -1125,7 +1146,7 @@
 
 /************************************************************/
 
-static void _finish_transaction()
+static void _finish_transaction(enum stm_event_e event)
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
 
@@ -1136,6 +1157,7 @@
     list_clear(STM_PSEGMENT->objects_pointing_to_nursery);
     list_clear(STM_PSEGMENT->old_objects_with_cards_set);
     list_clear(STM_PSEGMENT->large_overflow_objects);
+    timing_event(tl, event);
 
     release_thread_segment(tl);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
@@ -1147,6 +1169,8 @@
     struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         object_t *obj = undo->object;
         struct object_s *dst = (struct object_s*)REAL_ADDRESS(segbase, obj);
         assert(dst->stm_flags & GCFLAG_WRITE_BARRIER);
@@ -1236,7 +1260,7 @@
 
     /* done */
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
-    _finish_transaction();
+    _finish_transaction(STM_TRANSACTION_COMMIT);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     s_mutex_unlock();
@@ -1260,6 +1284,8 @@
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         object_t *obj = undo->object;
         char *dst = REAL_ADDRESS(pseg->pub.segment_base, obj);
 
@@ -1369,7 +1395,7 @@
                                                    : NURSERY_END;
     }
 
-    _finish_transaction();
+    _finish_transaction(STM_TRANSACTION_ABORT);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     return tl;
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
@@ -84,9 +84,12 @@
        track the STM status: these are old objects that where written
        to and that will need to be recorded in the commit log.  The
        list contains three entries for every such object, in the same
-       format as 'struct stm_undo_s' below.
+       format as 'struct stm_undo_s' below.  It can also represent a
+       position marker, like 'struct stm_undo_s'.
     */
     struct list_s *modified_old_objects;
+    uintptr_t position_markers_last;     /* index of most recent pos marker */
+    uintptr_t position_markers_len_old;  /* length of list at last minor col */
 
     struct list_s *objects_pointing_to_nursery;
     struct list_s *old_objects_with_cards_set;
@@ -174,18 +177,27 @@
 
 /* Commit Log things */
 struct stm_undo_s {
-    object_t *object;   /* the object that is modified */
-    char *backup;       /* some backup data (a slice of the original obj) */
-    uint64_t slice;     /* location and size of this slice (cannot cross
-                           pages).  The size is in the lower 2 bytes, and
-                           the offset in the remaining 6 bytes. */
+  union {
+    struct {
+        object_t *object;   /* the object that is modified */
+        char *backup;       /* some backup data (a slice of the original obj) */
+        uint64_t slice;     /* location and size of this slice (cannot cross
+                               pages).  The size is in the lower 2 bytes, and
+                               the offset in the remaining 6 bytes. */
+    };
+    struct {
+        intptr_t type;               /* TYPE_POSITION_MARKER */
+        uintptr_t marker_odd_number; /* the odd number part of the marker */
+        object_t *marker_object;     /* the object part of the marker */
+    };
+  };
 };
+#define TYPE_POSITION_MARKER    (-1)
 #define SLICE_OFFSET(slice)  ((slice) >> 16)
 #define SLICE_SIZE(slice)    ((int)((slice) & 0xFFFF))
 #define NEW_SLICE(offset, size) (((uint64_t)(offset)) << 16 | (size))
 
 
-
 /* The model is: we have a global chained list, from 'commit_log_root',
    of 'struct stm_commit_log_entry_s' entries.  Every one is fully
    read-only apart from the 'next' field.  Every one stands for one
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
@@ -348,6 +348,8 @@
         struct stm_undo_s *modified = (struct stm_undo_s *)lst->items;
         struct stm_undo_s *end = (struct stm_undo_s *)(lst->items + lst->count);
         for (; modified < end; modified++) {
+            if (modified->type == TYPE_POSITION_MARKER)
+                continue;
             object_t *obj = modified->object;
             struct object_s *dst = (struct object_s*)REAL_ADDRESS(base, obj);
 
@@ -386,6 +388,22 @@
     LIST_FREE(uniques);
 }
 
+static void mark_visit_from_markers(void)
+{
+    long i;
+    for (i = 1; i < NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
+        struct list_s *lst = get_priv_segment(i)->modified_old_objects;
+
+        struct stm_undo_s *modified = (struct stm_undo_s *)lst->items;
+        struct stm_undo_s *end = (struct stm_undo_s *)(lst->items + lst->count);
+        for (; modified < end; modified++) {
+            if (modified->type == TYPE_POSITION_MARKER)
+                mark_visit_possibly_new_object(modified->marker_object, pseg);
+        }
+    }
+}
+
 static void mark_visit_from_roots(void)
 {
     if (testing_prebuilt_objs != NULL) {
@@ -683,6 +701,7 @@
     /* marking */
     LIST_CREATE(marked_objects_to_trace);
     mark_visit_from_modified_objects();
+    mark_visit_from_markers();
     mark_visit_from_roots();
     mark_visit_from_finalizer_pending();
 
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,93 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#ifndef _STM_CORE_H_
+# error "must be compiled via stmgc.c"
+#endif
+
+static bool marker_fetch(stm_thread_local_t *tl, stm_loc_marker_t *out_marker)
+{
+    /* Fetch the current marker from tl's shadow stack,
+       and return it in 'out_marker->odd_number' and 'out_marker->object'. */
+    struct stm_shadowentry_s *current = tl->shadowstack - 1;
+    struct stm_shadowentry_s *base = tl->shadowstack_base;
+
+    /* The shadowstack_base contains -1, which is a convenient stopper for
+       the loop below but which shouldn't be returned. */
+    assert(base->ss == (object_t *)-1);
+
+    while (!(((uintptr_t)current->ss) & 1)) {
+        current--;
+        assert(current >= base);
+    }
+    if (current != base) {
+        /* found the odd marker */
+        out_marker->odd_number = (uintptr_t)current[0].ss;
+        out_marker->object = current[1].ss;
+        return true;
+    }
+    else {
+        /* no marker found */
+        return false;
+    }
+}
+
+static void marker_fetch_obj_write(struct stm_undo_s *start,
+                                   struct stm_undo_s *contention,
+                                   stm_loc_marker_t *out_marker)
+{
+    /* Fill out 'out_marker->odd_number' and 'out_marker->object' from
+       the marker just before 'contention' in the list starting at
+       'start'.
+    */
+    while (contention != start) {
+        --contention;
+        if (contention->type == TYPE_POSITION_MARKER) {
+            out_marker->odd_number = contention->marker_odd_number;
+            out_marker->object = contention->marker_object;
+            return;
+        }
+    }
+    /* no position marker found... */
+    out_marker->odd_number = 0;
+    out_marker->object = NULL;
+}
+
+static void _timing_record_write_position(void)
+{
+    stm_loc_marker_t marker;
+    if (!marker_fetch(STM_SEGMENT->running_thread, &marker))
+        return;
+
+    struct list_s *list = STM_PSEGMENT->modified_old_objects;
+    uintptr_t i = STM_PSEGMENT->position_markers_last;
+    if (i < list_count(list)) {
+        struct stm_undo_s *undo = (struct stm_undo_s *)(list->items + i);
+        if (undo->type == TYPE_POSITION_MARKER &&
+            undo->marker_odd_number == marker.odd_number &&
+            undo->marker_object == marker.object)
+            return;    /* already up-to-date */
+    }
+
+    STM_PSEGMENT->position_markers_last = list_count(list);
+    STM_PSEGMENT->modified_old_objects = list_append3(
+        list,
+        TYPE_POSITION_MARKER,         /* type */
+        marker.odd_number,            /* marker_odd_number */
+        (uintptr_t)marker.object);    /* marker_object */
+}
+
+static void timing_write_read_contention(struct stm_undo_s *start,
+                                         struct stm_undo_s *contention)
+{
+    if (stmcb_timing_event == NULL)
+        return;
+
+    stm_loc_marker_t marker;
+    marker_fetch_obj_write(start, contention, &marker);
+    stmcb_timing_event(STM_SEGMENT->running_thread,
+                       STM_CONTENTION_WRITE_READ, &marker);
+}
+
+
+void (*stmcb_timing_event)(stm_thread_local_t *tl, /* the local thread */
+                           enum stm_event_e event,
+                           stm_loc_marker_t *marker);
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,11 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+static void _timing_record_write_position(void);
+static void timing_write_read_contention(struct stm_undo_s *start,
+                                         struct stm_undo_s *contention);
+
+
+#define timing_event(tl, event)                                         \
+    (stmcb_timing_event != NULL ? stmcb_timing_event(tl, event, NULL) : (void)0)
+
+#define timing_record_write_position()                                  \
+    (stmcb_timing_event != NULL ? _timing_record_write_position() : (void)0)
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
@@ -185,6 +185,8 @@
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
     for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            continue;
         _cards_cleared_in_object(pseg, undo->object, false);
     }
     LIST_FOREACH_R(
@@ -410,6 +412,20 @@
     }
 }
 
+static void collect_roots_from_markers(uintptr_t len_old)
+{
+    dprintf(("collect_roots_from_markers\n"));
+
+    /* visit the marker objects */
+    struct list_s *list = STM_PSEGMENT->modified_old_objects;
+    struct stm_undo_s *undo = (struct stm_undo_s *)(list->items + len_old);
+    struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
+
+    for (; undo < end; undo++) {
+        if (undo->type == TYPE_POSITION_MARKER)
+            minor_trace_if_young(&undo->marker_object);
+    }
+}
 
 static void collect_objs_still_young_but_with_finalizers(void)
 {
@@ -494,14 +510,25 @@
     dprintf(("minor_collection commit=%d\n", (int)commit));
 
     STM_PSEGMENT->minor_collect_will_commit_now = commit;
+
+    uintptr_t len_old;
+    if (STM_PSEGMENT->overflow_number_has_been_used)
+        len_old = STM_PSEGMENT->position_markers_len_old;
+    else
+        len_old = 0;
+
     if (!commit) {
         /* 'STM_PSEGMENT->overflow_number' is used now by this collection,
            in the sense that it's copied to the overflow objects */
         STM_PSEGMENT->overflow_number_has_been_used = true;
+        STM_PSEGMENT->position_markers_len_old =
+            list_count(STM_PSEGMENT->modified_old_objects);
     }
 
     collect_cardrefs_to_nursery();
 
+    collect_roots_from_markers(len_old);
+
     collect_roots_in_nursery();
 
     if (STM_PSEGMENT->finalizers != NULL)
diff --git a/rpython/translator/stm/src_stm/stm/prof.c b/rpython/translator/stm/src_stm/stm/prof.c
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/src_stm/stm/prof.c
@@ -0,0 +1,122 @@
+/* Imported by rpython/translator/stm/import_stmgc.py */
+#include <stdio.h>
+#include <time.h>
+
+static FILE *profiling_file;
+static char *profiling_basefn = NULL;
+static stm_expand_marker_fn profiling_expand_marker;
+
+#define MARKER_LEN_MAX   160
+
+
+static bool close_timing_log(void);   /* forward */
+
+static void _stm_profiling_event(stm_thread_local_t *tl,
+                                 enum stm_event_e event,
+                                 stm_loc_marker_t *marker)
+{
+    struct buf_s {
+        uint32_t tv_sec;
+        uint32_t tv_nsec;
+        uint32_t thread_num;
+        uint8_t event;
+        uint8_t marker_length;
+        char extra[MARKER_LEN_MAX+1];
+    } __attribute__((packed));
+
+    struct buf_s buf;
+    struct timespec t;
+    clock_gettime(CLOCK_MONOTONIC, &t);
+    buf.tv_sec = t.tv_sec;
+    buf.tv_nsec = t.tv_nsec;
+    buf.thread_num = tl->thread_local_counter;
+    buf.event = event;
+    buf.marker_length = 0;
+
+    if (marker != NULL && marker->odd_number != 0) {
+        buf.marker_length = profiling_expand_marker(get_segment_base(0),
+                                                    marker,
+                                                    buf.extra, MARKER_LEN_MAX);
+    }
+
+    if (fwrite(&buf, offsetof(struct buf_s, extra) + buf.marker_length,
+               1, profiling_file) != 1) {
+        fprintf(stderr, "stmgc: profiling log file closed unexpectedly: %m\n");
+        close_timing_log();
+    }
+}
+
+static int default_expand_marker(char *b, stm_loc_marker_t *m, char *p, int s)
+{
+    *(uintptr_t *)p = m->odd_number;
+    return sizeof(uintptr_t);
+}
+
+static bool open_timing_log(const char *filename)
+{
+    profiling_file = fopen(filename, "w");
+    if (profiling_file == NULL)
+        return false;
+
+    fwrite("STMGC-C8-PROF01\n", 16, 1, profiling_file);
+    stmcb_timing_event = _stm_profiling_event;
+    return true;
+}
+
+static bool close_timing_log(void)
+{
+    if (stmcb_timing_event == &_stm_profiling_event) {
+        stmcb_timing_event = NULL;
+        fclose(profiling_file);
+        profiling_file = NULL;
+        return true;
+    }
+    return false;
+}
+
+static void prof_forksupport_prepare(void)
+{
+    if (profiling_file != NULL)
+        fflush(profiling_file);
+}
+
+static void prof_forksupport_child(void)
+{
+    if (close_timing_log() && profiling_basefn != NULL) {
+        char filename[1024];
+        snprintf(filename, sizeof(filename),
+                 "%s.fork%ld", profiling_basefn, (long)getpid());
+        open_timing_log(filename);
+    }
+}
+
+int stm_set_timing_log(const char *profiling_file_name, int fork_mode,
+                       stm_expand_marker_fn expand_marker)
+{
+    close_timing_log();
+    free(profiling_basefn);
+    profiling_basefn = NULL;
+
+    if (profiling_file_name == NULL)
+        return 0;
+
+    if (!expand_marker)
+        expand_marker = default_expand_marker;
+    profiling_expand_marker = expand_marker;
+
+    static bool fork_support_ready = false;
+    if (!fork_support_ready) {
+        int res = pthread_atfork(prof_forksupport_prepare,
+                                 NULL, prof_forksupport_child);
+        if (res != 0)
+            stm_fatalerror("pthread_atfork() failed: %m");
+        fork_support_ready = true;
+    }
+
+    if (!open_timing_log(profiling_file_name))
+        return -1;
+
+    if (fork_mode != 0)
+        profiling_basefn = strdup(profiling_file_name);
+    return 0;
+}
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
@@ -221,6 +221,8 @@
     return (pthread_t *)(tl->creating_pthread);
 }
 
+static int thread_local_counters = 0;
+
 void stm_register_thread_local(stm_thread_local_t *tl)
 {
     int num;
@@ -242,6 +244,7 @@
        numbers automatically. */
     tl->associated_segment_num = -1;
     tl->last_associated_segment_num = num + 1;
+    tl->thread_local_counter = ++thread_local_counters;
     *_get_cpth(tl) = pthread_self();
     _init_shadow_stack(tl);
     set_gs_register(get_segment_base(num + 1));
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/gcpage.h"
 #include "stm/extra.h"
 #include "stm/fprintcolor.h"
+#include "stm/marker.h"
 #include "stm/rewind_setjmp.h"
 #include "stm/finalizer.h"
 #include "stm/misc.c"
@@ -34,5 +35,7 @@
 #include "stm/core.c"
 #include "stm/extra.c"
 #include "stm/fprintcolor.c"
+#include "stm/marker.c"
+#include "stm/prof.c"
 #include "stm/rewind_setjmp.c"
 #include "stm/finalizer.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
@@ -68,6 +68,7 @@
     /* the next fields are handled internally by the library */
     int associated_segment_num;
     int last_associated_segment_num;
+    int thread_local_counter;
     struct stm_thread_local_s *prev, *next;
     void *creating_pthread[2];
 } stm_thread_local_t;
@@ -342,6 +343,69 @@
 void stm_resume_all_other_threads(void);
 
 
+/* Profiling events.  In the comments: content of the markers, if any */
+enum stm_event_e {
+    /* always STM_TRANSACTION_START followed later by one of COMMIT or ABORT */
+    STM_TRANSACTION_START,
+    STM_TRANSACTION_COMMIT,
+    STM_TRANSACTION_ABORT,
+
+    /* write-read contention: a "marker" is included in the PYPYSTM file
+       saying where the write was done.  Followed by STM_TRANSACTION_ABORT. */
+    STM_CONTENTION_WRITE_READ,
+
+    /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */
+    STM_WAIT_FREE_SEGMENT,
+    STM_WAIT_OTHER_INEVITABLE,
+    STM_WAIT_DONE,
+
+    /* start and end of GC cycles */
+    STM_GC_MINOR_START,
+    STM_GC_MINOR_DONE,
+    STM_GC_MAJOR_START,
+    STM_GC_MAJOR_DONE,
+
+    _STM_EVENT_N
+};
+
+#define STM_EVENT_NAMES                         \
+    "transaction start",                        \
+    "transaction commit",                       \
+    "transaction abort",                        \
+    "contention write read",                    \
+    "wait free segment",                        \
+    "wait other inevitable",                    \
+    "wait done",                                \
+    "gc minor start",                           \
+    "gc minor done",                            \
+    "gc major start",                           \
+    "gc major done"
+
+/* The markers pushed in the shadowstack are an odd number followed by a
+   regular object pointer. */
+typedef struct {
+    uintptr_t odd_number;
+    object_t *object;
+} stm_loc_marker_t;
+extern void (*stmcb_timing_event)(stm_thread_local_t *tl, /* the local thread */
+                                  enum stm_event_e event,
+                                  stm_loc_marker_t *marker);
+
+/* Calling this sets up a stmcb_timing_event callback that will produce
+   a binary file called 'profiling_file_name'.  Call it with
+   'fork_mode == 0' for only the main process, and with
+   'fork_mode == 1' to also write files called
+   'profiling_file_name.fork<PID>' after a fork().  Call it with NULL to
+   stop profiling.  Returns -1 in case of error (see errno then).
+   The optional 'expand_marker' function pointer is called to expand
+   the marker's odd_number and object into printable data, starting at
+   the given position and with the given maximum length. */
+typedef int (*stm_expand_marker_fn)(char *seg_base, stm_loc_marker_t *marker,
+                                    char *output, int output_size);
+int stm_set_timing_log(const char *profiling_file_name, int fork_mode,
+                       stm_expand_marker_fn expand_marker);
+
+
 /* Convenience macros to push the markers into the shadowstack */
 #define STM_PUSH_MARKER(tl, odd_num, p)   do {  \
     uintptr_t _odd_num = (odd_num);             \
diff --git a/rpython/translator/stm/src_stm/stmgcintf.h b/rpython/translator/stm/src_stm/stmgcintf.h
--- a/rpython/translator/stm/src_stm/stmgcintf.h
+++ b/rpython/translator/stm/src_stm/stmgcintf.h
@@ -42,14 +42,6 @@
 
 /* C8: not implemented properly yet: */
 extern void stmcb_commit_soon(void);
-typedef struct {
-    stm_thread_local_t *tl;
-    char *segment_base;    /* base to interpret the 'object' below */
-    uintptr_t odd_number;  /* marker odd number, or 0 if marker is missing */
-    object_t *object;      /* marker object, or NULL if marker is missing */
-} stm_loc_marker_t;
-static inline int stm_set_timing_log(const char *profiling_file_name, int fork_mode,
-                       int expand_marker(stm_loc_marker_t *, char *, int)) {return 0;}
 /* C8: not implemented properly yet ^^^^^^^^^^^^^^^^^^ */
 
 


More information about the pypy-commit mailing list