Author: Armin Rigo <[email protected]>
Branch:
Changeset: r236:531e5789c7dd
Date: 2013-06-22 15:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/531e5789c7dd/
Log: After a major GC, make sure the other threads abort if the major GC
found that they should.
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -59,16 +59,23 @@
static pthread_mutex_t mutex_inevitable = PTHREAD_MUTEX_INITIALIZER;
-static void inev_mutex_acquire(void)
+static void inev_mutex_release(void)
+{
+ pthread_mutex_unlock(&mutex_inevitable);
+}
+
+static void inev_mutex_acquire(struct tx_descriptor *d)
{ /* must save roots around this call */
stm_stop_sharedlock();
pthread_mutex_lock(&mutex_inevitable);
stm_start_sharedlock();
-}
-static void inev_mutex_release(void)
-{
- pthread_mutex_unlock(&mutex_inevitable);
+ if (d->active < 0)
+ {
+ inev_mutex_release();
+ AbortNowIfDelayed();
+ abort(); /* unreachable */
+ }
}
/************************************************************/
@@ -882,6 +889,7 @@
{
assert(d->active == 0);
stm_start_sharedlock();
+ assert(d->active == 0);
if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) {
d->start_real_time.tv_nsec = -1;
@@ -1225,7 +1233,7 @@
{ // there is another inevitable transaction
CancelLocks(d);
spinlock_release(d->public_descriptor->collection_lock);
- inev_mutex_acquire(); // wait until released
+ inev_mutex_acquire(d); // wait until released
inev_mutex_release();
spinlock_acquire(d->public_descriptor->collection_lock, 'C');
if (d->public_descriptor->stolen_objects.size != 0)
@@ -1284,11 +1292,12 @@
update_reads_size_limit(d);
}
-static revision_t acquire_inev_mutex_and_mark_global_cur_time(void)
+static revision_t acquire_inev_mutex_and_mark_global_cur_time(
+ struct tx_descriptor *d)
{ /* must save roots around this call */
revision_t cur_time;
- inev_mutex_acquire();
+ inev_mutex_acquire(d);
while (1)
{
cur_time = ACCESS_ONCE(global_cur_time);
@@ -1312,7 +1321,7 @@
fprintf(stderr, "[%lx] inevitable: %s\n",
(long)d->public_descriptor_index, why);
- cur_time = acquire_inev_mutex_and_mark_global_cur_time();
+ cur_time = acquire_inev_mutex_and_mark_global_cur_time(d);
if (d->start_time != cur_time)
{
d->start_time = cur_time;
@@ -1332,7 +1341,7 @@
revision_t cur_time;
init_transaction(d);
- cur_time = acquire_inev_mutex_and_mark_global_cur_time();
+ cur_time = acquire_inev_mutex_and_mark_global_cur_time(d);
d->start_time = cur_time;
make_inevitable(d);
}
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -378,8 +378,8 @@
if (IS_POINTER(v)) {
/* has a more recent revision. Oups. */
fprintf(stderr,
- "ABRT_COLLECT_MAJOR: %p was read but modified already\n",
- obj);
+ "ABRT_COLLECT_MAJOR %p: %p was read but modified
already\n",
+ d, obj);
AbortTransactionAfterCollect(d, ABRT_COLLECT_MAJOR);
return;
}
@@ -410,6 +410,8 @@
*/
wlog_t *item;
+ fprintf(stderr, "fix public_to_private on thread %p\n", d);
+
G2L_LOOP_FORWARD(d->public_to_private, item) {
assert(item->addr->h_tid & GCFLAG_PUBLIC);
@@ -419,6 +421,7 @@
(item->val->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
item->addr->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
+ fprintf(stderr, "\tpublic_to_private: %p\n", item->addr);
} G2L_LOOP_END;
diff --git a/c4/stmsync.c b/c4/stmsync.c
--- a/c4/stmsync.c
+++ b/c4/stmsync.c
@@ -293,6 +293,8 @@
/* another thread should be waiting in start_exclusivelock(),
which takes priority here */
stm_start_sharedlock();
+
+ AbortNowIfDelayed(); /* if another thread ran a major GC */
}
/************************************************************/
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -73,6 +73,7 @@
void stm_start_sharedlock(void);
void stm_stop_sharedlock(void);
void AbortTransaction(int);
+ void AbortNowIfDelayed(void);
gcptr stm_get_private_from_protected(long index);
gcptr stm_get_read_obj(long index);
void *STUB_THREAD(gcptr);
@@ -416,6 +417,7 @@
lib.stm_stop_sharedlock()
self.parallel_locks[1].acquire()
lib.stm_start_sharedlock()
+ lib.AbortNowIfDelayed()
print 'wait_while_in_parallel leave'
# parallel_locks[0] is acquired, parallel_locks[1] is acquired
self.parallel_locks[1].release()
@@ -500,9 +502,9 @@
return p.h_tid & GCFLAG_STUB
def check_not_free(p):
- print >> sys.stderr, "[checking %r..." % p,
+ #print >> sys.stderr, "[checking %r..." % p,
assert 42 < (p.h_tid & 0xFFFF) < 521
- print >> sys.stderr, "ok]"
+ #print >> sys.stderr, "ok]"
def check_nursery_free(p):
#assert p.h_tid == p.h_revision == 0
diff --git a/c4/test/test_random.py b/c4/test/test_random.py
--- a/c4/test/test_random.py
+++ b/c4/test/test_random.py
@@ -5,7 +5,7 @@
# a default seed that changes every day, but that can be easily recovered
DEFAULT_SEED = int(time.strftime("%y%m%d", time.gmtime()))
-DO_MAJOR_COLLECTS = False
+DO_MAJOR_COLLECTS = True
def setup_function(_):
@@ -452,6 +452,7 @@
self.toggle = not threadid
self.cond.notify()
lib.stm_start_sharedlock()
+ lib.AbortNowIfDelayed()
def wait1(self):
self.wait(False)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit