[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