Author: Remi Meier <[email protected]>
Branch: c8-new-page-handling
Changeset: r1503:15d0affd8675
Date: 2014-11-11 13:56 +0100
http://bitbucket.org/pypy/stmgc/changeset/15d0affd8675/
Log: fix deadlock
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -157,6 +157,8 @@
page_privatize_in(my_segnum, pagenum);
assert(get_page_status_in(my_segnum, pagenum) == PAGE_PRIVATE);
+ /* before copying anything, acquire modification locks from our and
+ the other segment */
uint64_t to_lock = (1UL << copy_from_segnum)| (1UL << my_segnum);
acquire_modification_lock_set(to_lock);
pagecopy((char*)(get_virt_page_of(my_segnum, pagenum) * 4096UL),
@@ -169,7 +171,6 @@
might need a walk into the past. */
struct stm_commit_log_entry_s *src_version, *target_version;
src_version = get_priv_segment(copy_from_segnum)->last_commit_log_entry;
- OPT_ASSERT(src_version->rev_num == most_recent_rev);
target_version = STM_PSEGMENT->last_commit_log_entry;
@@ -229,7 +230,7 @@
fprintf(stderr, "commit log:\n");
while ((cl = cl->next)) {
- if (cl == (void *)-1) {
+ if (cl == INEV_RUNNING) {
fprintf(stderr, " INEVITABLE\n");
return;
}
@@ -262,7 +263,7 @@
/* Don't check this 'cl'. This entry is already checked */
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
- assert(first_cl->next == (void*)-1);
+ assert(first_cl->next == INEV_RUNNING);
return;
}
@@ -270,13 +271,13 @@
uint64_t segments_to_lock = 1UL << my_segnum;
cl = first_cl;
while ((next_cl = cl->next) != NULL) {
- if (next_cl == (void *)-1) {
+ if (next_cl == INEV_RUNNING) {
#if STM_TESTS
if (free_if_abort != (void *)-1)
free(free_if_abort);
stm_abort_transaction();
#endif
- /* only go this far when validating */
+ /* only validate entries up to INEV */
break;
}
assert(next_cl->rev_num > cl->rev_num);
@@ -324,7 +325,10 @@
/* last fully validated entry */
STM_PSEGMENT->last_commit_log_entry = cl;
+ if (cl == last_cl)
+ break;
}
+ assert(cl == last_cl);
OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS));
int segnum;
@@ -346,6 +350,8 @@
if (needs_abort) {
if (free_if_abort != (void *)-1)
free(free_if_abort);
+ /* pages may be inconsistent */
+
stm_abort_transaction();
}
}
@@ -381,18 +387,25 @@
/* try to attach to commit log: */
old = STM_PSEGMENT->last_commit_log_entry;
if (old->next == NULL) {
- if ((uintptr_t)new != -1) /* INEVITABLE */
+ if (new != INEV_RUNNING) /* INEVITABLE */
new->rev_num = old->rev_num + 1;
if (__sync_bool_compare_and_swap(&old->next, NULL, new))
break; /* success! */
+ } else if (old->next == INEV_RUNNING) {
+ /* we failed because there is an INEV transaction running */
+ usleep(10);
}
+
+ /* check for requested safe point. otherwise an INEV transaction
+ may try to commit but cannot because of the busy-loop here. */
+ _stm_collectable_safe_point();
}
}
static void _validate_and_turn_inevitable(void)
{
- _validate_and_attach((struct stm_commit_log_entry_s *)-1);
+ _validate_and_attach((struct stm_commit_log_entry_s *)INEV_RUNNING);
}
static void _validate_and_add_to_commit_log(void)
@@ -403,9 +416,9 @@
if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
old = STM_PSEGMENT->last_commit_log_entry;
new->rev_num = old->rev_num + 1;
- OPT_ASSERT(old->next == (void *)-1);
+ OPT_ASSERT(old->next == INEV_RUNNING);
- bool yes = __sync_bool_compare_and_swap(&old->next, (void*)-1, new);
+ bool yes = __sync_bool_compare_and_swap(&old->next, INEV_RUNNING, new);
OPT_ASSERT(yes);
}
else {
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -123,6 +123,7 @@
data from 'written[n].backup' is the content of (slices of) the
object as they were *before* that commit occurred.
*/
+#define INEV_RUNNING ((void*)-1)
struct stm_commit_log_entry_s {
struct stm_commit_log_entry_s *volatile next;
int segment_num;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit