Merge pull request #10486 from rjmccall/nested-access-tracking-4.0
[4.0] Fix some embarrassing list-management bugs with the exclusivity runtime
diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp
index a5101f9..6cc91c9 100644
--- a/stdlib/public/runtime/Exclusivity.cpp
+++ b/stdlib/public/runtime/Exclusivity.cpp
@@ -150,7 +150,7 @@
void setNext(Access *next) {
NextAndAction =
- reinterpret_cast<uintptr_t>(next) | (NextAndAction & NextMask);
+ reinterpret_cast<uintptr_t>(next) | (NextAndAction & ActionMask);
}
ExclusivityFlags getAccessAction() const {
@@ -209,8 +209,11 @@
return;
}
- for (Access *last = cur; cur != nullptr; last = cur, cur = cur->getNext()) {
- if (last == access) {
+ Access *last = cur;
+ for (cur = cur->getNext(); cur != nullptr;
+ last = cur, cur = cur->getNext()) {
+ assert(last->getNext() == cur);
+ if (cur == access) {
last->setNext(cur->getNext());
return;
}
diff --git a/unittests/runtime/Exclusivity.cpp b/unittests/runtime/Exclusivity.cpp
index ab0e874..35a34fe 100644
--- a/unittests/runtime/Exclusivity.cpp
+++ b/unittests/runtime/Exclusivity.cpp
@@ -16,7 +16,7 @@
using namespace swift;
-TEST(TextExclusivity, testNullPC) {
+TEST(TestExclusivity, testNullPC) {
ValueBuffer scratch, scratch2;
long var;
swift_beginAccess(&var, &scratch,
@@ -29,7 +29,7 @@
swift_endAccess(&scratch);
}
-TEST(TextExclusivity, testPCOne) {
+TEST(TestExclusivity, testPCOne) {
ValueBuffer scratch, scratch2;
long var;
swift_beginAccess(&var, &scratch,
@@ -42,7 +42,7 @@
swift_endAccess(&scratch);
}
-TEST(TextExclusivity, testBogusPC) {
+TEST(TestExclusivity, testBogusPC) {
ValueBuffer scratch, scratch2;
long var;
swift_beginAccess(&var, &scratch,
@@ -54,3 +54,34 @@
swift_endAccess(&scratch2);
swift_endAccess(&scratch);
}
+
+// rdar://32866493
+TEST(TestExclusivity, testNonNested) {
+ const int N = 5;
+ ValueBuffer scratches[N];
+ long vars[N];
+
+ auto begin = [&](unsigned i) {
+ assert(i < N);
+ swift_beginAccess(&vars[i], &scratches[i], ExclusivityFlags::Modify, 0);
+ };
+ auto end = [&](unsigned i) {
+ assert(i < N);
+ swift_endAccess(&scratches[i]);
+ memset(&scratches[i], /*gibberish*/ 0x99, sizeof(ValueBuffer));
+ };
+ auto accessAll = [&] {
+ for (unsigned i = 0; i != N; ++i) begin(i);
+ for (unsigned i = 0; i != N; ++i) end(i);
+ };
+
+ accessAll();
+ begin(0); begin(1); end(0); end(1);
+ begin(0); begin(1); end(0); end(1);
+ accessAll();
+ begin(1); begin(0); begin(2); end(0); end(2); end(1);
+ accessAll();
+ begin(0); begin(1); begin(2); begin(3); begin(4);
+ end(1); end(4); end(0); end(2); end(3);
+ accessAll();
+}