Author: Armin Rigo <[email protected]>
Branch:
Changeset: r45:bcc91b3b1338
Date: 2013-05-27 18:59 +0200
http://bitbucket.org/pypy/stmgc/changeset/bcc91b3b1338/
Log: Phew. Found a bug, fixed it by preventing collapse of h_revision
chains from a GCFLAG_STOLEN object.
diff --git a/c3/Makefile b/c3/Makefile
--- a/c3/Makefile
+++ b/c3/Makefile
@@ -28,7 +28,7 @@
H_FILES = et.h lists.h nursery.h gcpage.h stmsync.h dbgmem.h fprintcolor.h
stmgc.h atomic_ops.h stmimpl.h
C_FILES = et.c lists.c nursery.c gcpage.c stmsync.c dbgmem.c fprintcolor.c
-DEBUG = -g -DGC_NURSERY=0x10000 -D_GC_DEBUG=2
+DEBUG = -g -DGC_NURSERY=0x10000 -D_GC_DEBUG=1
build-%: %.c ${H_FILES} ${C_FILES}
diff --git a/c3/demo1.c b/c3/demo1.c
--- a/c3/demo1.c
+++ b/c3/demo1.c
@@ -8,9 +8,10 @@
#include "stmgc.h"
+#include "fprintcolor.h"
-#define UPPER_BOUND 10
+#define UPPER_BOUND 100
#define NUMTHREADS 4
@@ -45,7 +46,7 @@
struct node *do_a_check(int seen[], int stress_gc)
{
int i;
- for (i=0; i<UPPER_BOUND; i++)
+ for (i=0; i<NUMTHREADS; i++)
seen[i] = 0;
struct node *r_n, *prev_n;
@@ -65,19 +66,18 @@
r_n = (struct node *)stm_read_barrier((gcptr)r_n->next);
long v = r_n->value;
- assert(0 <= v && v < UPPER_BOUND);
- if (v == 0)
- assert(seen[v] < NUMTHREADS);
- else
- assert(seen[v] < seen[v-1]);
- seen[v]++;
+ fprintf(stderr, "\t\t\t\t{ %ld, %p }\n", v, r_n->next);
+ assert(0 <= v && v < UPPER_BOUND * NUMTHREADS);
+ int tn = v / UPPER_BOUND;
+ assert(seen[tn] == v % UPPER_BOUND);
+ seen[tn]++;
}
return r_n;
}
int insert1(gcptr arg1, int retry_counter)
{
- int seen[UPPER_BOUND];
+ int seen[NUMTHREADS];
long nvalue;
struct node *r_arg;
@@ -92,10 +92,13 @@
GCTID_STRUCT_NODE);
last = (struct node *)stm_pop_root();
+ assert(seen[nvalue / UPPER_BOUND] == nvalue % UPPER_BOUND);
w_newnode->value = nvalue;
w_newnode->next = NULL;
+ fprintf(stderr, "DEMO1: %p->value = %ld\n", w_newnode, nvalue);
struct node *w_last = (struct node *)stm_write_barrier((gcptr)last);
+ fprintf(stderr, "DEMO1: %p->next = %p\n", w_last, w_newnode);
w_last->next = w_newnode;
return 0; /* return from stm_perform_transaction() */
@@ -105,18 +108,24 @@
extern void stmgcpage_possibly_major_collect(int force); /* temp */
+static int thr_mynum = 0;
+
void *demo1(void *arg)
{
- int i, status;
+ int i, status, start;
struct node *w_node;
stm_initialize();
+ start = thr_mynum++; /* protected by being inevitable here */
+ start *= UPPER_BOUND;
+ fprintf(stderr, "THREAD STARTING: start = %d\n", start);
+
w_node = (struct node *)stm_allocate(sizeof(struct node),
GCTID_STRUCT_NODE);
for (i=0; i<UPPER_BOUND; i++) {
w_node = (struct node *)stm_write_barrier((gcptr)w_node);
- w_node->value = i;
+ w_node->value = start + i;
stm_push_root((gcptr)w_node);
stm_perform_transaction((gcptr)w_node, insert1);
stmgcpage_possibly_major_collect(0); /* temp */
@@ -131,11 +140,15 @@
void final_check(void)
{
- int seen[UPPER_BOUND];
+ int i;
+ int seen[NUMTHREADS];
stm_initialize();
do_a_check(seen, 0);
- assert(seen[UPPER_BOUND-1] == NUMTHREADS);
+
+ for (i=0; i<NUMTHREADS; i++)
+ assert(seen[i] == UPPER_BOUND);
+
stm_finalize();
printf("check ok\n");
}
diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -93,7 +93,7 @@
gcptr R_prev = R;
R = (gcptr)v;
- /* retry */
+ retry_threelevels:
v = ACCESS_ONCE(R->h_revision);
if (!(v & 1)) // "is a pointer", i.e.
{ // "has a more recent revision"
@@ -103,15 +103,23 @@
/* we update R_prev->h_revision as a shortcut */
/* XXX check if this really gives a worse performance than only
doing this write occasionally based on a counter in d */
- R = (gcptr)v;
- if (R->h_revision == stm_local_revision)
+ gcptr R_next = (gcptr)v;
+ if (R_next->h_revision == stm_local_revision)
{
/* must not update an older h_revision to go directly to
the private copy at the end of a chain of protected
objects! */
- return R;
+ return R_next;
+ }
+ if (R_prev->h_tid & GCFLAG_STOLEN)
+ {
+ /* must not update the h_revision of a stolen object! */
+ R_prev = R;
+ R = R_next;
+ goto retry_threelevels;
}
R_prev->h_revision = v;
+ R = R_next;
goto retry;
}
}
@@ -505,7 +513,14 @@
gcptrlist_clear(&d->list_of_read_objects);
stmgc_abort_transaction(d);
- fprintf(stderr, "[%lx] abort %d\n", (long)d->my_lock, num);
+ fprintf(stderr,
+ "\n"
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "!!!!!!!!!!!!!!!!!!!!! [%lx] abort %d\n"
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "\n", (long)d->my_lock, num);
if (num != ABRT_MANUAL && d->max_aborts >= 0 && !d->max_aborts--)
{
fprintf(stderr, "unexpected abort!\n");
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -1116,7 +1116,7 @@
g2l_insert(&d->public_to_private, N, L);
gcptrlist_insert(&d->public_to_young, N);
}
- recdump1("STOLEN", R);
+ recdump1("WAS STOLEN", R);
/* then all items from i+2 up to the first NULL are new stubs
that must be added to d->public_to_young, in the first part
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit