[pypy-commit] stmgc default: Start to copy the abortinfo from pypy's stm-gc-2's rpyintf.c.

arigo noreply at buildbot.pypy.org
Sat Jul 6 12:08:47 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r355:5544b0de06cf
Date: 2013-07-06 11:39 +0200
http://bitbucket.org/pypy/stmgc/changeset/5544b0de06cf/

Log:	Start to copy the abortinfo from pypy's stm-gc-2's rpyintf.c.

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -922,9 +922,7 @@
 
   d->count_reads = 1;
   fxcache_clear(&d->recent_reads_cache);
-#if 0
   gcptrlist_clear(&d->abortinfo);
-#endif
 }
 
 void BeginTransaction(jmp_buf* buf)
@@ -1609,10 +1607,8 @@
     assert(d->private_from_protected.size == 0);
     gcptrlist_delete(&d->private_from_protected);
     gcptrlist_delete(&d->list_of_read_objects);
-#if 0
     gcptrlist_delete(&d->abortinfo);
     free(d->longest_abort_info);
-#endif
 
     int num_aborts = 0, num_spinloops = 0;
     char line[256], *p = line;
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -152,9 +152,9 @@
   unsigned int num_aborts[ABORT_REASONS];
   unsigned int num_spinloops[SPINLOOP_REASONS];
   struct GcPtrList list_of_read_objects;
-  //struct GcPtrList abortinfo;
   struct GcPtrList private_from_protected;
   struct G2L public_to_private;
+  struct GcPtrList abortinfo;
   char *longest_abort_info;
   long long longest_abort_info_time;
   revision_t *private_revision_ref;
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -137,3 +137,119 @@
         return 0;
     return stm_id(p1) == stm_id(p2);
 }
+
+/************************************************************/
+
+void stm_abort_info_push(gcptr obj, long fieldoffsets[])
+{
+    struct tx_descriptor *d = thread_descriptor;
+    gcptrlist_insert2(&d->abortinfo, obj, (gcptr)fieldoffsets);
+}
+
+void stm_abort_info_pop(long count)
+{
+    struct tx_descriptor *d = thread_descriptor;
+    long newsize = d->abortinfo.size - 2 * count;
+    gcptrlist_reduce_size(&d->abortinfo, newsize < 0 ? 0 : newsize);
+}
+
+#if 0
+size_t stm_decode_abort_info(struct tx_descriptor *d, long long elapsed_time,
+                             int abort_reason, char *output)
+{
+    /* re-encodes the abort info as a single string.
+       For convenience (no escaping needed, no limit on integer
+       sizes, etc.) we follow the bittorrent format. */
+    size_t totalsize = 0;
+    long i;
+    char buffer[32];
+    size_t res_size;
+#define WRITE(c)   { totalsize++; if (output) *output++=(c); }
+#define WRITE_BUF(p, sz)  { totalsize += (sz);                          \
+                            if (output) {                               \
+                                 memcpy(output, (p), (sz)); output += (sz); \
+                             }                                          \
+                           }
+    WRITE('l');
+    WRITE('l');
+    res_size = sprintf(buffer, "i%llde", (long long)elapsed_time);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%de", (int)abort_reason);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%lde", (long)d->public_descriptor_index);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%lde", (long)d->atomic);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%de", (int)d->active);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%lue", (unsigned long)d->count_reads);
+    WRITE_BUF(buffer, res_size);
+    res_size = sprintf(buffer, "i%lue",
+                       (unsigned long)d->reads_size_limit_nonatomic);
+    WRITE_BUF(buffer, res_size);
+    WRITE('e');
+    for (i=0; i<d->abortinfo.size; i+=2) {
+        char *object = (char *)stm_RepeatReadBarrier(d->abortinfo.items[i+0]);
+        long *fieldoffsets = (long*)d->abortinfo.items[i+1];
+        long kind, offset;
+        size_t rps_size;
+        RPyString *rps;
+
+        while (1) {
+            kind = *fieldoffsets++;
+            if (kind <= 0) {
+                if (kind == -2) {
+                    WRITE('l');    /* '[', start of sublist */
+                    continue;
+                }
+                if (kind == -1) {
+                    WRITE('e');    /* ']', end of sublist */
+                    continue;
+                }
+                break;   /* 0, terminator */
+            }
+            offset = *fieldoffsets++;
+            switch(kind) {
+            case 1:    /* signed */
+                res_size = sprintf(buffer, "i%lde",
+                                   *(long*)(object + offset));
+                WRITE_BUF(buffer, res_size);
+                break;
+            case 2:    /* unsigned */
+                res_size = sprintf(buffer, "i%lue",
+                                   *(unsigned long*)(object + offset));
+                WRITE_BUF(buffer, res_size);
+                break;
+            case 3:    /* pointer to STR */
+                rps = *(RPyString **)(object + offset);
+                if (rps) {
+                    rps_size = RPyString_Size(rps);
+                    res_size = sprintf(buffer, "%zu:", rps_size);
+                    WRITE_BUF(buffer, res_size);
+                    WRITE_BUF(_RPyString_AsString(rps), rps_size);
+                }
+                else {
+                    WRITE_BUF("0:", 2);
+                }
+                break;
+            default:
+                fprintf(stderr, "Fatal RPython error: corrupted abort log\n");
+                abort();
+            }
+        }
+    }
+    WRITE('e');
+    WRITE('\0');   /* final null character */
+#undef WRITE
+    return totalsize;
+}
+#endif
+
+char *stm_inspect_abort_info(void)
+{
+    struct tx_descriptor *d = thread_descriptor;
+    if (d->longest_abort_info_time <= 0)
+        return NULL;
+    d->longest_abort_info_time = 0;
+    return d->longest_abort_info;
+}
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -101,6 +101,18 @@
    It is set to NULL by stm_initialize(). */
 extern __thread gcptr stm_thread_local_obj;
 
+/* For tracking where aborts occurs, you can push/pop information
+   into this stack.  When an abort occurs this information is encoded
+   and flattened into a buffer which can later be retrieved with
+   stm_inspect_abort_info().  (XXX details not documented yet) */
+void stm_abort_info_push(gcptr obj, long fieldoffsets[]);
+void stm_abort_info_pop(long count);
+char *stm_inspect_abort_info(void);
+
+
+
+/****************  END OF PUBLIC INTERFACE  *****************/
+/************************************************************/
 
 
 /* macro-like functionality */
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -65,6 +65,9 @@
     long stm_atomic(long delta);
     int stm_enter_callback_call(void);
     void stm_leave_callback_call(int);
+    void stm_abort_info_push(void *obj, void *fieldoffsets);
+    void stm_abort_info_pop(long count);
+    char *stm_inspect_abort_info(void);
 
     /* extra non-public code */
     void printfcolor(char *msg);
diff --git a/c4/test/test_extra.py b/c4/test/test_extra.py
new file mode 100644
--- /dev/null
+++ b/c4/test/test_extra.py
@@ -0,0 +1,19 @@
+import py
+from support import *
+
+
+def setup_function(f):
+    lib.stm_clear_between_tests()
+    lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
+
+def teardown_function(_):
+    lib.stm_finalize()
+
+
+def test_abort_info_stack():
+    p = nalloc(HDR)
+    q = nalloc(HDR)
+    lib.stm_abort_info_push(p, ffi.cast("void *", 123))
+    lib.stm_abort_info_push(q, ffi.cast("void *", 125))
+    lib.stm_abort_info_pop(2)
+    # no real test here


More information about the pypy-commit mailing list