Author: Armin Rigo <[email protected]>
Branch: stm-gc-2
Changeset: r63118:ef7cc6c7f545
Date: 2013-04-07 17:44 +0200
http://bitbucket.org/pypy/pypy/changeset/ef7cc6c7f545/
Log: The minimal interface that should be enough to synchronize all
threads at the start of a major GC
diff --git a/rpython/translator/stm/src_stm/et.c
b/rpython/translator/stm/src_stm/et.c
--- a/rpython/translator/stm/src_stm/et.c
+++ b/rpython/translator/stm/src_stm/et.c
@@ -393,6 +393,8 @@
size_t size;
struct timespec now;
long long elapsed_time;
+ int err;
+
assert(d->active);
assert(!is_inevitable(d));
assert(num < ABORT_REASONS);
@@ -476,7 +478,8 @@
SpinLoop(0);
// jump back to the setjmp_buf (this call does not return)
d->active = 0;
- pthread_rwlock_unlock(&rwlock_in_transaction);
+ err = pthread_rwlock_unlock(&rwlock_in_transaction);
+ assert(err == 0);
longjmp(*d->setjmp_buf, 1);
}
@@ -491,8 +494,11 @@
static void init_transaction(struct tx_descriptor *d)
{
+ int err;
assert(d->active == 0);
- pthread_rwlock_rdlock(&rwlock_in_transaction);
+ err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+ assert(err == 0);
+
if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) {
d->start_real_time.tv_nsec = -1;
}
@@ -643,6 +649,7 @@
{
revision_t cur_time;
struct tx_descriptor *d = thread_descriptor;
+ int err;
assert(d->active != 0);
FindRootsForLocalCollect(d);
@@ -689,7 +696,8 @@
gcptrlist_clear(&d->gcroots);
d->num_commits++;
d->active = 0;
- pthread_rwlock_unlock(&rwlock_in_transaction);
+ err = pthread_rwlock_unlock(&rwlock_in_transaction);
+ assert(err == 0);
}
/************************************************************/
diff --git a/rpython/translator/stm/src_stm/rpyintf.c
b/rpython/translator/stm/src_stm/rpyintf.c
--- a/rpython/translator/stm/src_stm/rpyintf.c
+++ b/rpython/translator/stm/src_stm/rpyintf.c
@@ -63,6 +63,9 @@
}
static unsigned long stm_regular_length_limit = ULONG_MAX;
+static volatile int break_please = 0;
+
+static void reached_safe_point(void);
void stm_add_atomic(long delta)
{
@@ -106,6 +109,9 @@
assert(d->reads_size_limit_nonatomic == 0);
#endif
+ if (break_please)
+ reached_safe_point();
+
return d->count_reads > d->reads_size_limit;
}
@@ -173,6 +179,9 @@
if (!d->atomic)
BeginTransaction(&_jmpbuf);
+ if (break_please)
+ reached_safe_point();
+
/* invoke the callback in the new transaction */
result = callback(arg, counter);
@@ -192,6 +201,53 @@
PYPY_DEBUG_STOP("stm-perform-transaction");
}
+static struct tx_descriptor *in_single_thread = NULL; /* for debugging */
+
+void stm_start_single_thread(void)
+{
+ /* Called by the GC, just after a minor collection, when we need to do
+ a major collection. When it returns, it acquired the "write lock"
+ which prevents any other thread from running a transaction. */
+ int err;
+ break_please = 1;
+ err = pthread_rwlock_unlock(&rwlock_in_transaction);
+ assert(err == 0);
+ err = pthread_rwlock_wrlock(&rwlock_in_transaction);
+ assert(err == 0);
+ break_please = 0;
+
+ assert(in_single_thread == NULL);
+ in_single_thread = thread_descriptor;
+ assert(in_single_thread != NULL);
+}
+
+void stm_stop_single_thread(void)
+{
+ int err;
+
+ assert(in_single_thread == thread_descriptor);
+ in_single_thread = NULL;
+
+ err = pthread_rwlock_unlock(&rwlock_in_transaction);
+ assert(err == 0);
+ err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+ assert(err == 0);
+}
+
+static void reached_safe_point(void)
+{
+ int err;
+ struct tx_descriptor *d = thread_descriptor;
+ assert(in_single_thread != d);
+ if (d->active)
+ {
+ err = pthread_rwlock_unlock(&rwlock_in_transaction);
+ assert(err == 0);
+ err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+ assert(err == 0);
+ }
+}
+
void stm_abort_and_retry(void)
{
AbortTransaction(4); /* manual abort */
diff --git a/rpython/translator/stm/test/test_stmgcintf.c
b/rpython/translator/stm/test/test_stmgcintf.c
--- a/rpython/translator/stm/test/test_stmgcintf.c
+++ b/rpython/translator/stm/test/test_stmgcintf.c
@@ -344,6 +344,22 @@
/************************************************************/
+void single_thread_1(void)
+{
+ stm_start_single_thread();
+ stm_stop_single_thread();
+ stm_start_single_thread();
+ stm_stop_single_thread();
+ /* check that the assert() included in these functions don't trigger */
+}
+
+void test_single_thread(void)
+{
+ run_in_transaction(single_thread_1, '.');
+}
+
+/************************************************************/
+
#define XTEST(name) if (!strcmp(argv[1], #name)) { test_##name(); return 0; }
@@ -361,6 +377,7 @@
XTEST(duplicator);
XTEST(try_inevitable);
XTEST(should_break_transaction);
+ XTEST(single_thread);
printf("bad test name\n");
return 1;
}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit