summaryrefslogtreecommitdiff
path: root/src/debug/ee/datatest.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/ee/datatest.h')
-rw-r--r--src/debug/ee/datatest.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/debug/ee/datatest.h b/src/debug/ee/datatest.h
new file mode 100644
index 0000000000..7715ba5621
--- /dev/null
+++ b/src/debug/ee/datatest.h
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//*****************************************************************************
+// File: DataTest.h
+//
+
+//
+// Implement a self-test for the correct detection of when the target holds a
+// lock we encounter in the DAC.
+//
+//*****************************************************************************
+
+#ifndef DATA_TEST_H
+#define DATA_TEST_H
+
+// This class is used to test our ability to detect from the RS when the target has taken a lock.
+// When the DAC executes a code path that takes a lock, we need to know if the target is holding it.
+// If it is, then we assume that the locked data is in an inconsistent state. In that case, we don't
+// want to report the data; we just want to throw an exception.
+// This functionality in this class lets us take a lock on the LS and then signal the RS to try to
+// detect whether the lock is held. The main function in this class is TestDataSafety. It deterministically
+// signals the RS at key points to execute a code path that takes a lock and also passes a flag to indicate
+// whether the LS actually holds the lock. With this information, we can ascertain that our lock detection
+// code is working correctly. Without this special test function, it would be nearly impossible to test this
+// in any kind of deterministic way.
+//
+// The test will run in either debug or retail builds, as long as the environment variable TestDataConsistency
+// is turned on. It runs once in code:Debugger::Startup. The RS part of the test is in the cases
+// DB_IPCE_TEST_CRST and DB_IPCE_TEST_RWLOCK in code:CordbProcess::RawDispatchEvent.
+class DataTest
+{
+public:
+ // constructor
+ DataTest():
+ m_crst1(CrstDataTest1),
+ m_crst2(CrstDataTest2),
+ m_rwLock(COOPERATIVE_OR_PREEMPTIVE, LOCK_TYPE_DEFAULT) {};
+
+ // Takes a series of locks in various ways and signals the RS to test the locks at interesting
+ // points to ensure we reliably detect when the LS holds a lock.
+ void TestDataSafety();
+private:
+ // Send an event to the RS to signal that it should test to determine if a crst is held.
+ // This is for testing purposes only.
+ void SendDbgCrstEvent(Crst * pCrst, bool okToTake);
+
+ // Send an event to the RS to signal that it should test to determine if a SimpleRWLock is held.
+ // This is for testing purposes only.
+ void SendDbgRWLockEvent(SimpleRWLock * pRWLock, bool okToTake);
+
+private:
+ // The locks must be data members (rather than locals in TestDataSafety) so we can ensure that
+ // they are target instances.
+ Crst m_crst1, m_crst2; // crsts to be taken for testing
+ SimpleRWLock m_rwLock; // SimpleRWLock to be taken for testing
+};
+#endif // DATA_TEST_H