Author: Remi Meier <[email protected]>
Branch:
Changeset: r199:b2ce4052626c
Date: 2013-06-20 08:40 +0200
http://bitbucket.org/pypy/stmgc/changeset/b2ce4052626c/
Log: demo_random: more checks
diff --git a/c4/demo_random.c b/c4/demo_random.c
--- a/c4/demo_random.c
+++ b/c4/demo_random.c
@@ -6,15 +6,19 @@
#include <time.h>
#include "stmgc.h"
+#include "stmimpl.h"
#include "fprintcolor.h"
+extern revision_t get_private_rev_num(void);
+
#define NUMTHREADS 4
#define STEPS 100000
-#define NUMROOTS 10
-#define PREBUILT 3
+#define NUMROOTS 10 // per thread
+#define PREBUILT 3 // per thread
#define MAXROOTS 1000
-#define SHARED_ROOTS 5
+#define SHARED_ROOTS 5 // shared by threads
+
// SUPPORT
@@ -58,6 +62,9 @@
// helper functions
+int classify(gcptr p);
+void check(gcptr p);
+
int get_rand(int max)
{
return (int)(rand_r(&td.thread_seed) % (unsigned int)max);
@@ -81,15 +88,19 @@
void push_roots()
{
int i;
- for (i = 0; i < td.num_roots; i++)
+ for (i = 0; i < td.num_roots; i++) {
+ check(td.roots[i]);
stm_push_root(td.roots[i]);
+ }
}
void pop_roots()
{
int i;
- for (i = td.num_roots - 1; i >= 0; i--)
+ for (i = td.num_roots - 1; i >= 0; i--) {
td.roots[i] = stm_pop_root();
+ check(td.roots[i]);
+ }
}
void del_root(int idx)
@@ -99,15 +110,117 @@
td.roots[i] = td.roots[i + 1];
}
-gcptr allocate_node(size_t size, int tid)
+nodeptr allocate_node()
{
- gcptr r;
+ nodeptr r;
push_roots();
- r = stm_allocate(size, tid);
+ r = (nodeptr)stm_allocate(sizeof(struct node), GCTID_STRUCT_NODE);
pop_roots();
return r;
}
+int is_shared_prebuilt(gcptr p)
+{
+ int i;
+ for (i = 0; i < SHARED_ROOTS; i++)
+ if (shared_roots[i] == p)
+ return 1;
+ return 0;
+}
+
+void check_not_free(gcptr p)
+{
+ assert(p != NULL);
+ assert((p->h_tid & 0xFFFF) == GCTID_STRUCT_NODE);
+ if (is_shared_prebuilt(p))
+ assert(p->h_tid & GCFLAG_PREBUILT_ORIGINAL);
+}
+
+void check(gcptr p)
+{
+ if (p != NULL) {
+ check_not_free(p);
+ classify(p); // additional asserts
+ }
+}
+
+gcptr read_barrier(gcptr p)
+{
+ gcptr r = p;
+ if (p != NULL) {
+ check(p);
+ r = stm_read_barrier(p);
+ check(r);
+ }
+ return r;
+}
+
+gcptr write_barrier(gcptr p)
+{
+ gcptr w = p;
+ if (p != NULL) {
+ check(p);
+ w = stm_write_barrier(p);
+ check(w);
+ }
+ return w;
+}
+
+int in_nursery(gcptr obj)
+{
+ struct tx_descriptor *d = thread_descriptor;
+ int result1 = (d->nursery_base <= (char*)obj &&
+ ((char*)obj) < d->nursery_end);
+ if (obj->h_tid & GCFLAG_OLD) {
+ assert(result1 == 0);
+ }
+ else {
+ /* this assert() also fails if "obj" is in another nursery than
+ the one of the current thread. This is ok, because we
+ should not see such pointers. */
+ assert(result1 == 1);
+ }
+ return result1;
+}
+
+static const revision_t C_PRIVATE_FROM_PROTECTED = 1;
+static const revision_t C_PRIVATE = 2;
+static const revision_t C_STUB = 3;
+static const revision_t C_PUBLIC = 4;
+static const revision_t C_BACKUP = 5;
+static const revision_t C_PROTECTED = 6;
+int classify(gcptr p)
+{
+ int priv_from_prot = (p->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) != 0;
+ int private_other = p->h_revision == get_private_rev_num();
+ int public = (p->h_tid & GCFLAG_PUBLIC) != 0;
+ int backup = (p->h_tid & GCFLAG_BACKUP_COPY) != 0;
+ int stub = (p->h_tid & GCFLAG_STUB) != 0;
+ assert(priv_from_prot + private_other + public + backup <= 1);
+ assert(public || !stub);
+
+ if (priv_from_prot)
+ return C_PRIVATE_FROM_PROTECTED;
+ if (private_other)
+ return C_PRIVATE;
+ if (public) {
+ if (stub) {
+ assert(!in_nursery(p));
+ }
+ else {
+ if (in_nursery(p)) {
+ assert(p->h_tid & GCFLAG_NURSERY_MOVED);
+ assert(!(p->h_revision & 1));
+ }
+ return C_PUBLIC;
+ }
+ }
+ if (backup)
+ return C_BACKUP;
+ return C_PROTECTED;
+}
+
+
// THREAD TESTER
@@ -128,7 +241,7 @@
GCTID_STRUCT_NODE);
}
for (i = PREBUILT; i < PREBUILT + NUMROOTS; i++) {
- td.roots[i] = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE);
+ td.roots[i] = (gcptr)allocate_node();
}
}
@@ -149,9 +262,6 @@
k = get_rand(14);
- if (!p) // some parts expect it to be != 0
- p = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE);
-
switch (k) {
case 0: // remove a root
if (num > 0)
@@ -162,19 +272,21 @@
p = _r;
break;
case 2: // add 'p' to roots
- if (td.num_roots < MAXROOTS)
+ if (p && td.num_roots < MAXROOTS)
td.roots[td.num_roots++] = p;
break;
case 3: // allocate fresh 'p'
- p = allocate_node(sizeof(struct node), GCTID_STRUCT_NODE);
+ p = (gcptr)allocate_node();
break;
case 4: // set 'p' as *next in one of the roots
- w_r = (nodeptr)stm_write_barrier(_r);
- // XXX: do I have to read_barrier(p)?
+ check(_r);
+ w_r = (nodeptr)write_barrier(_r);
+ check((gcptr)w_r);
+ check(p);
w_r->next = (struct node*)p;
break;
case 5: // read and validate 'p'
- stm_read_barrier(p);
+ read_barrier(p);
break;
case 6: // transaction break
if (td.interruptible)
@@ -183,25 +295,27 @@
p = NULL;
break;
case 7: // only do a stm_write_barrier
- p = stm_write_barrier(p);
+ p = write_barrier(p);
break;
case 8:
- p = (gcptr)(((nodeptr)stm_read_barrier(p))->next);
+ if (p)
+ p = (gcptr)(((nodeptr)read_barrier(p))->next);
break;
case 9: // XXX: rare events
break;
case 10: // only do a stm_read_barrier
- p = stm_read_barrier(p);
+ p = read_barrier(p);
break;
case 11:
- stm_read_barrier(_sr);
+ read_barrier(_sr);
break;
case 12:
- stm_write_barrier(_sr);
+ write_barrier(_sr);
break;
case 13:
- w_sr = (nodeptr)stm_write_barrier(_sr);
+ w_sr = (nodeptr)write_barrier(_sr);
w_sr->next = (nodeptr)shared_roots[get_rand(SHARED_ROOTS)];
+ break;
default:
break;
}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit