提交 15a167bd 编写于 作者: V Vladimir Sadov 提交者: GitHub

Merge pull request dotnet/coreclr#23325 from VSadov/CmpExchA64

Resolve 22303   (interlocked failures on ARM64)

Commit migrated from https://github.com/dotnet/coreclr/commit/e5bfd7d89ad0704a23545ac1e6d6a80918e2dbe5
...@@ -571,24 +571,6 @@ ...@@ -571,24 +571,6 @@
<ExcludeList Include="$(XunitTestBinBase)/GC/Scenarios/Dynamo/dynamo/*"> <ExcludeList Include="$(XunitTestBinBase)/GC/Scenarios/Dynamo/dynamo/*">
<Issue>17129</Issue> <Issue>17129</Issue>
</ExcludeList> </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/compareexchange/CompareExchangeTClass/*">
<Issue>22303</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/compareexchange/CompareExchangeTClass_1/*">
<Issue>22303</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/exchange/ExchangeTClass/*">
<Issue>22303</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/exchange/ExchangeTString/*">
<Issue>22303</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/exchange/ExchangeTString_1/*">
<Issue>22303</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/baseservices/threading/interlocked/exchange/ExchangeTString_2/*">
<Issue>22303</Issue>
</ExcludeList>
</ItemGroup> </ItemGroup>
<!-- Unix arm32 specific --> <!-- Unix arm32 specific -->
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestExecutionArguments>null</CLRTestExecutionArguments> <CLRTestExecutionArguments>""</CLRTestExecutionArguments>
<CLRTestPriority>1</CLRTestPriority> <CLRTestPriority>1</CLRTestPriority>
<GCStressIncompatible>true</GCStressIncompatible> <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup> </PropertyGroup>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildAndRun</CLRTestKind> <CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>1</CLRTestPriority> <CLRTestPriority>1</CLRTestPriority>
<CLRTestExecutionArguments>empty</CLRTestExecutionArguments> <CLRTestExecutionArguments>"hello"</CLRTestExecutionArguments>
</PropertyGroup> </PropertyGroup>
<!-- Default configurations to help VS understand the configurations --> <!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
class Class1 class Class1
{ {
static int Main(string[] args) static int Main(string[] args)
{ {
int rValue = 0; int rValue = 0;
...@@ -21,21 +21,21 @@ static int Main(string[] args) ...@@ -21,21 +21,21 @@ static int Main(string[] args)
threads[i] = new Thread(new ParameterizedThreadStart(tsi.ThreadWorker)); threads[i] = new Thread(new ParameterizedThreadStart(tsi.ThreadWorker));
threads[i].Start(kcIn); threads[i].Start(kcIn);
} }
tsi.Signal(); tsi.Signal();
Console.WriteLine("Joining threads"); Console.WriteLine("Joining threads");
for(int i=0;i<threads.Length;i++) for (int i = 0; i < threads.Length; i++)
threads[i].Join(); threads[i].Join();
// Build the expected string // Build the expected string
KrisClass kcExpected = new KrisClass("hello world! "); KrisClass kcExpected = new KrisClass("hello world! ");
for(int i=0;i<threads.Length * 100;i++) for (int i = 0; i < threads.Length * 100; i++)
kcExpected = kcExpected + kcIn; kcExpected = kcExpected + kcIn;
if(kcExpected == tsi.GetValue) if (kcExpected == tsi.GetValue)
rValue = 100; rValue = 100;
Console.WriteLine("Test Expected {0}, but found {1}", kcExpected, tsi.GetValue); Console.WriteLine("Test Expected {0}, but found {1}", kcExpected, tsi.GetValue);
Console.WriteLine("Test {0}", rValue == 100 ? "Passed" : "Failed"); Console.WriteLine("Test {0}", rValue == 100 ? "Passed" : "Failed");
return rValue; return rValue;
} }
...@@ -44,9 +44,9 @@ static int Main(string[] args) ...@@ -44,9 +44,9 @@ static int Main(string[] args)
public class ThreadSafe public class ThreadSafe
{ {
ManualResetEvent signal; ManualResetEvent signal;
public KrisClass Val = new KrisClass("hello world! "); public KrisClass Val = new KrisClass("hello world! ");
private int numberOfIterations; private int numberOfIterations;
public ThreadSafe(): this(100) { } public ThreadSafe() : this(100) { }
public ThreadSafe(int loops) public ThreadSafe(int loops)
{ {
signal = new ManualResetEvent(false); signal = new ManualResetEvent(false);
...@@ -62,21 +62,23 @@ public void ThreadWorker(Object objIn) ...@@ -62,21 +62,23 @@ public void ThreadWorker(Object objIn)
{ {
KrisClass kcIn = (KrisClass)objIn; KrisClass kcIn = (KrisClass)objIn;
signal.WaitOne(); signal.WaitOne();
for(int i=0;i<numberOfIterations;i++) for (int i = 0; i < numberOfIterations; i++)
AddToTotal(kcIn); AddToTotal(kcIn);
} }
private KrisClass AddToTotal(KrisClass addend) private KrisClass AddToTotal(KrisClass addend)
{ {
KrisClass initialValue = new KrisClass(string.Empty); KrisClass initialValue;
KrisClass newValue = new KrisClass(string.Empty); KrisClass newValue;
do do
{ {
initialValue = Val; initialValue = Val;
newValue = initialValue + addend; newValue = initialValue + addend;
} }
while (initialValue != Interlocked.CompareExchange<KrisClass>( while ((object)initialValue != Interlocked.CompareExchange<KrisClass>(
ref Val, newValue, initialValue)); ref Val, newValue, initialValue));
return newValue; return newValue;
} }
...@@ -104,7 +106,7 @@ public string ClassVal ...@@ -104,7 +106,7 @@ public string ClassVal
return retVal; return retVal;
} }
} }
public static KrisClass operator +(KrisClass kc1, KrisClass kc2) public static KrisClass operator +(KrisClass kc1, KrisClass kc2)
{ {
return new KrisClass(kc1.ClassVal + kc2.ClassVal); return new KrisClass(kc1.ClassVal + kc2.ClassVal);
...@@ -112,7 +114,7 @@ public string ClassVal ...@@ -112,7 +114,7 @@ public string ClassVal
public static bool operator ==(KrisClass kc1, KrisClass kc2) public static bool operator ==(KrisClass kc1, KrisClass kc2)
{ {
if(kc1.ClassVal == kc2.ClassVal) if (kc1.ClassVal == kc2.ClassVal)
return true; return true;
else else
return false; return false;
...@@ -120,26 +122,26 @@ public string ClassVal ...@@ -120,26 +122,26 @@ public string ClassVal
public static bool operator !=(KrisClass kc1, KrisClass kc2) public static bool operator !=(KrisClass kc1, KrisClass kc2)
{ {
if(kc1.ClassVal != kc2.ClassVal) if (kc1.ClassVal != kc2.ClassVal)
return true; return true;
else else
return false; return false;
} }
public override bool Equals(object o) public override bool Equals(object o)
{ {
try try
{ {
return (bool) (this == (KrisClass) o); return (bool)(this == (KrisClass)o);
} }
catch catch
{ {
return false; return false;
} }
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return 0; return 0;
} }
} }
\ No newline at end of file
...@@ -95,8 +95,9 @@ private string AddToTotal(string addend) ...@@ -95,8 +95,9 @@ private string AddToTotal(string addend)
initialValue = Val; initialValue = Val;
newValue = initialValue + addend; newValue = initialValue + addend;
} }
while (initialValue != Interlocked.CompareExchange<string>( while ((object)initialValue != Interlocked.CompareExchange<string>(
ref Val, newValue, initialValue)); ref Val, newValue, initialValue));
return newValue; return newValue;
} }
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
using System.Collections; using System.Collections;
class Class1 class Class1
{ {
static int Main(string[] args) static int Main(string[] args)
{ {
int rValue = 0; int rValue = 0;
...@@ -17,10 +17,10 @@ static int Main(string[] args) ...@@ -17,10 +17,10 @@ static int Main(string[] args)
for (int i = 0; i < threads.Length - 1; i++) for (int i = 0; i < threads.Length - 1; i++)
{ {
if (i % 2 == 0) if (i % 2 == 0)
threads[i] = new Thread(new threads[i] = new Thread(new
ParameterizedThreadStart(tsi.ThreadWorkerA)); ParameterizedThreadStart(tsi.ThreadWorkerA));
else else
threads[i] = new Thread(new threads[i] = new Thread(new
ParameterizedThreadStart(tsi.ThreadWorkerB)); ParameterizedThreadStart(tsi.ThreadWorkerB));
threads[i].Start(args); threads[i].Start(args);
...@@ -30,12 +30,6 @@ static int Main(string[] args) ...@@ -30,12 +30,6 @@ static int Main(string[] args)
threads[threads.Length - 1] = new Thread(new ThreadStart(tsi.ThreadChecker)); threads[threads.Length - 1] = new Thread(new ThreadStart(tsi.ThreadChecker));
threads[threads.Length - 1].Start(); threads[threads.Length - 1].Start();
//Added to prevent races where Checker does not get to Wait before ManualEvent is Set
while(tsi.ThreadCount < 100)
{
Thread.Sleep(100);
}
Thread.Sleep(100);
tsi.Signal(); tsi.Signal();
Console.WriteLine("Joining threads"); Console.WriteLine("Joining threads");
...@@ -57,11 +51,8 @@ public class ThreadSafe ...@@ -57,11 +51,8 @@ public class ThreadSafe
private string newValueA = "hello"; private string newValueA = "hello";
private string newValueB = "world"; private string newValueB = "world";
private bool success; private bool success;
public volatile int ThreadCount = 0;
private volatile static object syncroot = new object(); public ThreadSafe() : this(10000) { }
public ThreadSafe(): this(10000) { }
public ThreadSafe(int loops) public ThreadSafe(int loops)
{ {
...@@ -81,28 +72,23 @@ public void ThreadWorkerA(object obj) ...@@ -81,28 +72,23 @@ public void ThreadWorkerA(object obj)
string ret = null; string ret = null;
// get the value // get the value
if(0 < str.Length) if (0 < str.Length)
{ {
if("null" == str[0]) if ("null" == str[0])
newValueA = null; newValueA = null;
else if("empty" == str[0]) else if ("empty" == str[0])
newValueA = string.Empty; newValueA = string.Empty;
else else
newValueA = str[0]; newValueA = str[0];
} }
lock(syncroot)
{
ThreadCount++;
}
signal.WaitOne(); signal.WaitOne();
for (int i = 0; i < numberOfIterations; i++) for (int i = 0; i < numberOfIterations; i++)
{ {
ret = Interlocked.Exchange<string>(ref curVal, newValueA); ret = Interlocked.Exchange<string>(ref curVal, newValueA);
// Check return value // Check return value
if(ret != newValueB && ret != newValueA && ret != "start string") if (ret != newValueB && ret != newValueA && ret != "start string")
{ {
Console.WriteLine(ret + "," + newValueB + "," + newValueA); Console.WriteLine(ret + "," + newValueB + "," + newValueA);
success = false; success = false;
...@@ -117,28 +103,24 @@ public void ThreadWorkerB(object obj) ...@@ -117,28 +103,24 @@ public void ThreadWorkerB(object obj)
string ret = null; string ret = null;
// get the value // get the value
if(2 == str.Length) if (2 == str.Length)
{ {
if("null" == str[1]) if ("null" == str[1])
newValueB = null; newValueB = null;
else if("empty" == str[1]) else if ("empty" == str[1])
newValueB = string.Empty; newValueB = string.Empty;
else else
newValueB = str[1]; newValueB = str[1];
} }
lock(syncroot) signal.WaitOne();
{
ThreadCount++;
}
signal.WaitOne();
for (int i = 0; i < numberOfIterations; i++) for (int i = 0; i < numberOfIterations; i++)
{ {
ret = Interlocked.Exchange<string>(ref curVal, newValueB); ret = Interlocked.Exchange<string>(ref curVal, newValueB);
// Check return value // Check return value
if(ret != newValueB && ret != newValueA && ret != "start string") if (ret != newValueB && ret != newValueA && ret != "start string")
{ {
Console.WriteLine(ret + "," + newValueB + "," + newValueA); Console.WriteLine(ret + "," + newValueB + "," + newValueA);
success = false; success = false;
...@@ -148,17 +130,18 @@ public void ThreadWorkerB(object obj) ...@@ -148,17 +130,18 @@ public void ThreadWorkerB(object obj)
public void ThreadChecker() public void ThreadChecker()
{ {
lock(syncroot)
{
ThreadCount++;
}
signal.WaitOne(); signal.WaitOne();
while(curVal == "start string")
{
Thread.Sleep(0);
}
string tmpVal; string tmpVal;
for (int i = 0; i < numberOfIterations; i++) for (int i = 0; i < numberOfIterations; i++)
{ {
tmpVal = curVal; tmpVal = curVal;
if (tmpVal != newValueB && tmpVal != newValueA && tmpVal != "start string") if (tmpVal != newValueB && tmpVal != newValueA)
{ {
Console.WriteLine(tmpVal + "," + newValueB + "," + newValueA); Console.WriteLine(tmpVal + "," + newValueB + "," + newValueA);
success = false; success = false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册