From 21132fe05ea51e86100b20b6a06c4db8c61fba92 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 11:34:49 -0400 Subject: [PATCH 1/6] Add Locking Abstractions --- inc/cxplat.hpp | 39 +++++++++++++++++ inc/cxplat_posix.h | 63 ++++++++++++++++++++++++++ inc/cxplat_winkernel.h | 58 ++++++++++++++++++++++++ inc/cxplat_winuser.h | 45 +++++++++++++++++++ src/test/CxPlatTests.h | 14 +++++- src/test/bin/cxplat_gtest.cpp | 18 ++++++++ src/test/bin/winkernel/control.cpp | 10 +++++ src/test/lib/CMakeLists.txt | 1 + src/test/lib/LockTest.cpp | 68 +++++++++++++++++++++++++++++ src/test/lib/testlib.kernel.vcxproj | 1 + src/test/lib/testlib.user.vcxproj | 1 + 11 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 src/test/lib/LockTest.cpp diff --git a/inc/cxplat.hpp b/inc/cxplat.hpp index 4e1c7cd..4c60fd1 100644 --- a/inc/cxplat.hpp +++ b/inc/cxplat.hpp @@ -19,6 +19,45 @@ #include "cxplat.h" #include "cxplat_sal_stub.h" +struct CxPlatLock { + CXPLAT_LOCK Handle; + CxPlatLock() noexcept { CxPlatLockInitialize(&Handle); } + ~CxPlatLock() noexcept { CxPlatLockUninitialize(&Handle); } + void Acquire() noexcept { CxPlatLockAcquire(&Handle); } + void Release() noexcept { CxPlatLockRelease(&Handle); } +}; + +struct CxPlatRwLock { + CXPLAT_RW_LOCK Handle; + CxPlatRwLock() noexcept { CxPlatRwLockInitialize(&Handle); } + ~CxPlatRwLock() noexcept { CxPlatRwLockUninitialize(&Handle); } + void AcquireShared() noexcept { CxPlatRwLockAcquireShared(&Handle); } + void AcquireExclusive() noexcept { CxPlatRwLockAcquireExclusive(&Handle); } + void ReleaseShared() noexcept { CxPlatRwLockReleaseShared(&Handle); } + void ReleaseExclusive() noexcept { CxPlatRwLockReleaseExclusive(&Handle); } +}; + +#pragma warning(push) +#pragma warning(disable:28167) // TODO - Fix SAL annotations for IRQL changes +struct CxPlatLockDispatch { + CXPLAT_DISPATCH_LOCK Handle; + CxPlatLockDispatch() noexcept { CxPlatDispatchLockInitialize(&Handle); } + ~CxPlatLockDispatch() noexcept { CxPlatDispatchLockUninitialize(&Handle); } + void Acquire() noexcept { CxPlatDispatchLockAcquire(&Handle); } + void Release() noexcept { CxPlatDispatchLockRelease(&Handle); } +}; + +struct CxPlatRwLockDispatch { + CXPLAT_DISPATCH_RW_LOCK Handle; + CxPlatRwLockDispatch() noexcept { CxPlatDispatchRwLockInitialize(&Handle); } + ~CxPlatRwLockDispatch() noexcept { CxPlatDispatchRwLockUninitialize(&Handle); } + void AcquireShared() noexcept { CxPlatDispatchRwLockAcquireShared(&Handle); } + void AcquireExclusive() noexcept { CxPlatDispatchRwLockAcquireExclusive(&Handle); } + void ReleaseShared() noexcept { CxPlatDispatchRwLockReleaseShared(&Handle); } + void ReleaseExclusive() noexcept { CxPlatDispatchRwLockReleaseExclusive(&Handle); } +}; +#pragma warning(pop) + typedef void* CxPlatCallback( _Inout_ void* Context ); diff --git a/inc/cxplat_posix.h b/inc/cxplat_posix.h index 203179c..89abe77 100644 --- a/inc/cxplat_posix.h +++ b/inc/cxplat_posix.h @@ -134,6 +134,69 @@ CxPlatFree( #define CxPlatMoveMemory(Destination, Source, Length) memmove((Destination), (Source), (Length)) #define CxPlatSecureZeroMemory CxPlatZeroMemory // TODO - Something better? +// +// Interrupt ReQuest Level +// + +#define CXPLAT_IRQL() 0 +#define CXPLAT_PASSIVE_CODE() +#define CXPLAT_AT_DISPATCH() FALSE + +// +// Locking interfaces +// + +typedef struct CXPLAT_LOCK { + alignas(16) pthread_mutex_t Mutex; +} CXPLAT_LOCK; + +#define CxPlatLockInitialize(Lock) { \ + pthread_mutexattr_t Attr; \ + CXPLAT_FRE_ASSERT(pthread_mutexattr_init(&Attr) == 0); \ + CXPLAT_FRE_ASSERT(pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE) == 0); \ + CXPLAT_FRE_ASSERT(pthread_mutex_init(&(Lock)->Mutex, &Attr) == 0); \ + CXPLAT_FRE_ASSERT(pthread_mutexattr_destroy(&Attr) == 0); \ +} +#define CxPlatLockUninitialize(Lock) \ + CXPLAT_FRE_ASSERT(pthread_mutex_destroy(&(Lock)->Mutex) == 0) +#define CxPlatLockAcquire(Lock) \ + CXPLAT_FRE_ASSERT(pthread_mutex_lock(&(Lock)->Mutex) == 0) +#define CxPlatLockRelease(Lock) \ + CXPLAT_FRE_ASSERT(pthread_mutex_unlock(&(Lock)->Mutex) == 0) + +typedef CXPLAT_LOCK CXPLAT_DISPATCH_LOCK; + +#define CxPlatDispatchLockInitialize CxPlatLockInitialize +#define CxPlatDispatchLockUninitialize CxPlatLockUninitialize +#define CxPlatDispatchLockAcquire CxPlatLockAcquire +#define CxPlatDispatchLockRelease CxPlatLockRelease + +typedef struct CXPLAT_RW_LOCK { + pthread_rwlock_t RwLock; +} CXPLAT_RW_LOCK; + +#define CxPlatRwLockInitialize(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_init(&(Lock)->RwLock, NULL) == 0) +#define CxPlatRwLockUninitialize(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_destroy(&(Lock)->RwLock) == 0) +#define CxPlatRwLockAcquireShared(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_rdlock(&(Lock)->RwLock) == 0) +#define CxPlatRwLockAcquireExclusive(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_wrlock(&(Lock)->RwLock) == 0) +#define CxPlatRwLockReleaseShared(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_unlock(&(Lock)->RwLock) == 0) +#define CxPlatRwLockReleaseExclusive(Lock) \ + CXPLAT_FRE_ASSERT(pthread_rwlock_unlock(&(Lock)->RwLock) == 0) + +typedef CXPLAT_RW_LOCK CXPLAT_DISPATCH_RW_LOCK; + +#define CxPlatDispatchRwLockInitialize CxPlatRwLockInitialize +#define CxPlatDispatchRwLockUninitialize CxPlatRwLockUninitialize +#define CxPlatDispatchRwLockAcquireShared CxPlatRwLockAcquireShared +#define CxPlatDispatchRwLockAcquireExclusive CxPlatRwLockAcquireExclusive +#define CxPlatDispatchRwLockReleaseShared CxPlatRwLockReleaseShared +#define CxPlatDispatchRwLockReleaseExclusive CxPlatRwLockReleaseExclusive + // // Time Measurement Interfaces // diff --git a/inc/cxplat_winkernel.h b/inc/cxplat_winkernel.h index 5bfcc55..54dd6ad 100644 --- a/inc/cxplat_winkernel.h +++ b/inc/cxplat_winkernel.h @@ -125,6 +125,64 @@ CxPlatLogAssert( #define CxPlatMoveMemory RtlMoveMemory #define CxPlatSecureZeroMemory RtlSecureZeroMemory +// +// Interrupt ReQuest Level +// + +#define CXPLAT_IRQL() KeGetCurrentIrql() + +#define CXPLAT_PASSIVE_CODE() CXPLAT_DBG_ASSERT(CXPLAT_IRQL() == PASSIVE_LEVEL) +#define CXPLAT_AT_DISPATCH() (CXPLAT_IRQL() == DISPATCH_LEVEL) + +#define CXPLAT_RAISE_IRQL() KIRQL OldIrql; KeRaiseIrql(DISPATCH_LEVEL, &OldIrql) +#define CXPLAT_LOWER_IRQL() KeLowerIrql(OldIrql) + +// +// Locking Interfaces +// + +typedef EX_PUSH_LOCK CXPLAT_LOCK; + +#define CxPlatLockInitialize(Lock) ExInitializePushLock(Lock) +#define CxPlatLockUninitialize(Lock) +#define CxPlatLockAcquire(Lock) KeEnterCriticalRegion(); ExAcquirePushLockExclusive(Lock) +#define CxPlatLockRelease(Lock) ExReleasePushLockExclusive(Lock); KeLeaveCriticalRegion() + +typedef struct CXPLAT_DISPATCH_LOCK { + KSPIN_LOCK SpinLock; + KIRQL PrevIrql; +} CXPLAT_DISPATCH_LOCK; + +#define CxPlatDispatchLockInitialize(Lock) KeInitializeSpinLock(&(Lock)->SpinLock) +#define CxPlatDispatchLockUninitialize(Lock) +#if defined(_AMD64_) || defined(_ARM64_) +#define CxPlatDispatchLockAcquire(Lock) (Lock)->PrevIrql = KeAcquireSpinLockRaiseToDpc(&(Lock)->SpinLock) +#else +#define CxPlatDispatchLockAcquire(Lock) KeAcquireSpinLock(&(Lock)->SpinLock, &(Lock)->PrevIrql) +#endif +#define CxPlatDispatchLockRelease(Lock) KeReleaseSpinLock(&(Lock)->SpinLock, (Lock)->PrevIrql) + +typedef EX_PUSH_LOCK CXPLAT_RW_LOCK; + +#define CxPlatRwLockInitialize(Lock) ExInitializePushLock(Lock) +#define CxPlatRwLockUninitialize(Lock) +#define CxPlatRwLockAcquireShared(Lock) KeEnterCriticalRegion(); ExAcquirePushLockShared(Lock) +#define CxPlatRwLockAcquireExclusive(Lock) KeEnterCriticalRegion(); ExAcquirePushLockExclusive(Lock) +#define CxPlatRwLockReleaseShared(Lock) ExReleasePushLockShared(Lock); KeLeaveCriticalRegion() +#define CxPlatRwLockReleaseExclusive(Lock) ExReleasePushLockExclusive(Lock); KeLeaveCriticalRegion() + +typedef struct CXPLAT_DISPATCH_RW_LOCK { + EX_SPIN_LOCK SpinLock; + KIRQL PrevIrql; +} CXPLAT_DISPATCH_RW_LOCK; + +#define CxPlatDispatchRwLockInitialize(Lock) (Lock)->SpinLock = 0 +#define CxPlatDispatchRwLockUninitialize(Lock) +#define CxPlatDispatchRwLockAcquireShared(Lock) (Lock)->PrevIrql = ExAcquireSpinLockShared(&(Lock)->SpinLock) +#define CxPlatDispatchRwLockAcquireExclusive(Lock) (Lock)->PrevIrql = ExAcquireSpinLockExclusive(&(Lock)->SpinLock) +#define CxPlatDispatchRwLockReleaseShared(Lock) ExReleaseSpinLockShared(&(Lock)->SpinLock, (Lock)->PrevIrql) +#define CxPlatDispatchRwLockReleaseExclusive(Lock) ExReleaseSpinLockExclusive(&(Lock)->SpinLock, (Lock)->PrevIrql) + // // Time Measurement Interfaces // diff --git a/inc/cxplat_winuser.h b/inc/cxplat_winuser.h index 29986de..6a59c20 100644 --- a/inc/cxplat_winuser.h +++ b/inc/cxplat_winuser.h @@ -152,6 +152,51 @@ CxPlatFree( #define CxPlatMoveMemory RtlMoveMemory #define CxPlatSecureZeroMemory RtlSecureZeroMemory +// +// Interrupt ReQuest Level +// + +#define CXPLAT_IRQL() PASSIVE_LEVEL + +#define CXPLAT_PASSIVE_CODE() CXPLAT_DBG_ASSERT(CXPLAT_IRQL() == PASSIVE_LEVEL) +#define CXPLAT_AT_DISPATCH() FALSE + +// +// Locking interfaces +// + +typedef CRITICAL_SECTION CXPLAT_LOCK; + +#define CxPlatLockInitialize(Lock) InitializeCriticalSection(Lock) +#define CxPlatLockUninitialize(Lock) DeleteCriticalSection(Lock) +#define CxPlatLockAcquire(Lock) EnterCriticalSection(Lock) +#define CxPlatLockRelease(Lock) LeaveCriticalSection(Lock) + +typedef CRITICAL_SECTION CXPLAT_DISPATCH_LOCK; + +#define CxPlatDispatchLockInitialize(Lock) InitializeCriticalSection(Lock) +#define CxPlatDispatchLockUninitialize(Lock) DeleteCriticalSection(Lock) +#define CxPlatDispatchLockAcquire(Lock) EnterCriticalSection(Lock) +#define CxPlatDispatchLockRelease(Lock) LeaveCriticalSection(Lock) + +typedef SRWLOCK CXPLAT_RW_LOCK; + +#define CxPlatRwLockInitialize(Lock) InitializeSRWLock(Lock) +#define CxPlatRwLockUninitialize(Lock) +#define CxPlatRwLockAcquireShared(Lock) AcquireSRWLockShared(Lock) +#define CxPlatRwLockAcquireExclusive(Lock) AcquireSRWLockExclusive(Lock) +#define CxPlatRwLockReleaseShared(Lock) ReleaseSRWLockShared(Lock) +#define CxPlatRwLockReleaseExclusive(Lock) ReleaseSRWLockExclusive(Lock) + +typedef SRWLOCK CXPLAT_DISPATCH_RW_LOCK; + +#define CxPlatDispatchRwLockInitialize(Lock) InitializeSRWLock(Lock) +#define CxPlatDispatchRwLockUninitialize(Lock) +#define CxPlatDispatchRwLockAcquireShared(Lock) AcquireSRWLockShared(Lock) +#define CxPlatDispatchRwLockAcquireExclusive(Lock) AcquireSRWLockExclusive(Lock) +#define CxPlatDispatchRwLockReleaseShared(Lock) ReleaseSRWLockShared(Lock) +#define CxPlatDispatchRwLockReleaseExclusive(Lock) ReleaseSRWLockExclusive(Lock) + // // Time Measurement Interfaces // diff --git a/src/test/CxPlatTests.h b/src/test/CxPlatTests.h index b63f1c0..bfef30b 100644 --- a/src/test/CxPlatTests.h +++ b/src/test/CxPlatTests.h @@ -64,6 +64,12 @@ void CxPlatTestThreadWaitTimeout(); // void VectorBasic(); +// +// Lock Tests +// +void CxPlatTestLockBasic(); +void CxPlatTestLockReadWrite(); + // // Platform Specific Functions // @@ -145,4 +151,10 @@ static const GUID CXPLAT_TEST_DEVICE_INSTANCE = #define IOCTL_CXPLAT_RUN_THREAD_ASYNC \ CXPLAT_CTL_CODE(9, METHOD_BUFFERED, FILE_WRITE_DATA) -#define CXPLAT_MAX_IOCTL_FUNC_CODE 9 +#define IOCTL_CXPLAT_RUN_LOCK_BASIC \ + CXPLAT_CTL_CODE(10, METHOD_BUFFERED, FILE_WRITE_DATA) + +#define IOCTL_CXPLAT_RUN_LOCK_READ_WRITE \ + CXPLAT_CTL_CODE(11, METHOD_BUFFERED, FILE_WRITE_DATA) + +#define CXPLAT_MAX_IOCTL_FUNC_CODE 11 diff --git a/src/test/bin/cxplat_gtest.cpp b/src/test/bin/cxplat_gtest.cpp index 64c2973..28ddc28 100644 --- a/src/test/bin/cxplat_gtest.cpp +++ b/src/test/bin/cxplat_gtest.cpp @@ -200,6 +200,24 @@ TEST(VectorSuite, Basic) { } } +TEST(LockSuite, Basic) { + TestLogger Logger("CxPlatTestLockBasic"); + if (TestingKernelMode) { + ASSERT_TRUE(DriverClient.Run(IOCTL_CXPLAT_RUN_LOCK_BASIC)); + } else { + CxPlatTestLockBasic(); + } +} + +TEST(LockSuite, ReadWrite) { + TestLogger Logger("CxPlatTestLockReadWrite"); + if (TestingKernelMode) { + ASSERT_TRUE(DriverClient.Run(IOCTL_CXPLAT_RUN_LOCK_READ_WRITE)); + } else { + CxPlatTestLockReadWrite(); + } +} + int main(int argc, char** argv) { for (int i = 0; i < argc; ++i) { if (strcmp("--kernel", argv[i]) == 0) { diff --git a/src/test/bin/winkernel/control.cpp b/src/test/bin/winkernel/control.cpp index a7a4ce6..b47863d 100644 --- a/src/test/bin/winkernel/control.cpp +++ b/src/test/bin/winkernel/control.cpp @@ -367,6 +367,8 @@ size_t CXPLAT_IOCTL_BUFFER_SIZES[] = 0, 0, 0, + 0, + 0, }; static_assert( @@ -513,6 +515,14 @@ CxPlatTestCtlEvtIoDeviceControl( CxPlatTestCtlRun(VectorBasic()); break; + case IOCTL_CXPLAT_RUN_LOCK_BASIC: + CxPlatTestCtlRun(CxPlatTestLockBasic()); + break; + + case IOCTL_CXPLAT_RUN_LOCK_READ_WRITE: + CxPlatTestCtlRun(CxPlatTestLockReadWrite()); + break; + default: Status = STATUS_NOT_IMPLEMENTED; break; diff --git a/src/test/lib/CMakeLists.txt b/src/test/lib/CMakeLists.txt index 458907e..93889e2 100644 --- a/src/test/lib/CMakeLists.txt +++ b/src/test/lib/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES CryptTest.cpp EventTest.cpp + LockTest.cpp MemoryTest.cpp ProcTest.cpp ThreadTest.cpp diff --git a/src/test/lib/LockTest.cpp b/src/test/lib/LockTest.cpp new file mode 100644 index 0000000..04f69f8 --- /dev/null +++ b/src/test/lib/LockTest.cpp @@ -0,0 +1,68 @@ +/*++ + + Copyright (c) Microsoft Corporation. + Licensed under the MIT License. + +Abstract: + + Lock test. + +--*/ + +#include "precomp.h" + +void CxPlatTestLockBasic() +{ +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + + { + CxPlatLock Lock; + Lock.Acquire(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + Lock.Release(); + } + + { + CxPlatLockDispatch Lock; + Lock.Acquire(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_TRUE(CXPLAT_AT_DISPATCH()); +#endif + Lock.Release(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + } +} + +void CxPlatTestLockReadWrite() +{ +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + + { + CxPlatRwLock Lock; + Lock.AcquireShared(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + Lock.AcquireExclusive(); + } + + { + CxPlatRwLockDispatch Lock; + Lock.AcquireShared(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_TRUE(CXPLAT_AT_DISPATCH()); +#endif + Lock.AcquireExclusive(); +#if defined(CX_PLATFORM_WINKERNEL) + TEST_FALSE(CXPLAT_AT_DISPATCH()); +#endif + } +} diff --git a/src/test/lib/testlib.kernel.vcxproj b/src/test/lib/testlib.kernel.vcxproj index 0ed741a..0076769 100644 --- a/src/test/lib/testlib.kernel.vcxproj +++ b/src/test/lib/testlib.kernel.vcxproj @@ -21,6 +21,7 @@ + diff --git a/src/test/lib/testlib.user.vcxproj b/src/test/lib/testlib.user.vcxproj index a8ccf96..6178c8d 100644 --- a/src/test/lib/testlib.user.vcxproj +++ b/src/test/lib/testlib.user.vcxproj @@ -21,6 +21,7 @@ + From 2abc963fff6c7c54f26e45abf08e14906802cf3e Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 11:37:38 -0400 Subject: [PATCH 2/6] formatting --- inc/cxplat_posix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/cxplat_posix.h b/inc/cxplat_posix.h index 89abe77..dc314a0 100644 --- a/inc/cxplat_posix.h +++ b/inc/cxplat_posix.h @@ -158,7 +158,7 @@ typedef struct CXPLAT_LOCK { CXPLAT_FRE_ASSERT(pthread_mutexattr_destroy(&Attr) == 0); \ } #define CxPlatLockUninitialize(Lock) \ - CXPLAT_FRE_ASSERT(pthread_mutex_destroy(&(Lock)->Mutex) == 0) + CXPLAT_FRE_ASSERT(pthread_mutex_destroy(&(Lock)->Mutex) == 0) #define CxPlatLockAcquire(Lock) \ CXPLAT_FRE_ASSERT(pthread_mutex_lock(&(Lock)->Mutex) == 0) #define CxPlatLockRelease(Lock) \ From ba85b87e0ffbefb6e37717b60602ba2d0e6beff6 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 11:39:31 -0400 Subject: [PATCH 3/6] more tests --- src/test/lib/LockTest.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/test/lib/LockTest.cpp b/src/test/lib/LockTest.cpp index 04f69f8..07bb192 100644 --- a/src/test/lib/LockTest.cpp +++ b/src/test/lib/LockTest.cpp @@ -37,6 +37,19 @@ void CxPlatTestLockBasic() TEST_FALSE(CXPLAT_AT_DISPATCH()); #endif } + +#if defined(CX_PLATFORM_WINKERNEL) + { + CxPlatLockDispatch Lock; + CXPLAT_RAISE_IRQL(); + Lock.Acquire(); + TEST_TRUE(CXPLAT_AT_DISPATCH()); + Lock.Release(); + TEST_TRUE(CXPLAT_AT_DISPATCH()); + CXPLAT_LOWER_IRQL(); + TEST_FALSE(CXPLAT_AT_DISPATCH()); + } +#endif } void CxPlatTestLockReadWrite() @@ -51,7 +64,7 @@ void CxPlatTestLockReadWrite() #if defined(CX_PLATFORM_WINKERNEL) TEST_FALSE(CXPLAT_AT_DISPATCH()); #endif - Lock.AcquireExclusive(); + Lock.ReleaseShared(); } { @@ -60,9 +73,22 @@ void CxPlatTestLockReadWrite() #if defined(CX_PLATFORM_WINKERNEL) TEST_TRUE(CXPLAT_AT_DISPATCH()); #endif - Lock.AcquireExclusive(); + Lock.ReleaseShared(); #if defined(CX_PLATFORM_WINKERNEL) TEST_FALSE(CXPLAT_AT_DISPATCH()); #endif } + +#if defined(CX_PLATFORM_WINKERNEL) + { + CxPlatLockDispatch Lock; + CXPLAT_RAISE_IRQL(); + Lock.AcquireShared(); + TEST_TRUE(CXPLAT_AT_DISPATCH()); + Lock.ReleaseShared(); + TEST_TRUE(CXPLAT_AT_DISPATCH()); + CXPLAT_LOWER_IRQL(); + TEST_FALSE(CXPLAT_AT_DISPATCH()); + } +#endif } From 6c771a55489d7b23e485fbefad9c463d24c0d887 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 11:42:27 -0400 Subject: [PATCH 4/6] Fix kernel test --- src/test/lib/LockTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/lib/LockTest.cpp b/src/test/lib/LockTest.cpp index 07bb192..36becfc 100644 --- a/src/test/lib/LockTest.cpp +++ b/src/test/lib/LockTest.cpp @@ -81,7 +81,7 @@ void CxPlatTestLockReadWrite() #if defined(CX_PLATFORM_WINKERNEL) { - CxPlatLockDispatch Lock; + CxPlatRwLockDispatch Lock; CXPLAT_RAISE_IRQL(); Lock.AcquireShared(); TEST_TRUE(CXPLAT_AT_DISPATCH()); From d316b37acc700d2740fc97ccf7b8322f1ba691a4 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 13:26:12 -0400 Subject: [PATCH 5/6] More tests --- inc/cxplat.hpp | 2 -- src/test/lib/LockTest.cpp | 18 ++++++++++++++++++ src/test/lib/ThreadTest.cpp | 8 ++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/inc/cxplat.hpp b/inc/cxplat.hpp index a6d3e2a..14dd2af 100644 --- a/inc/cxplat.hpp +++ b/inc/cxplat.hpp @@ -63,8 +63,6 @@ struct CxPlatEvent { CxPlatEvent() noexcept { CxPlatEventInitialize(&Handle, FALSE, FALSE); } CxPlatEvent(bool ManualReset) noexcept { CxPlatEventInitialize(&Handle, ManualReset, FALSE); } CxPlatEvent(CXPLAT_EVENT event) noexcept : Handle(event) { } - ~CxPlatEvent() noexcept { CxPlatEventUninitialize(Handle); } - CXPLAT_EVENT* operator &() noexcept { return &Handle; } operator CXPLAT_EVENT() const noexcept { return Handle; } void Set() { CxPlatEventSet(Handle); } void Reset() { CxPlatEventReset(Handle); } diff --git a/src/test/lib/LockTest.cpp b/src/test/lib/LockTest.cpp index 36becfc..5580076 100644 --- a/src/test/lib/LockTest.cpp +++ b/src/test/lib/LockTest.cpp @@ -50,6 +50,24 @@ void CxPlatTestLockBasic() TEST_FALSE(CXPLAT_AT_DISPATCH()); } #endif + + { + CxPlatEvent Event; + CxPlatLock Lock; + struct Context { + CxPlatEvent* Event; + CxPlatLock* Lock; + } Ctx = { &Event, &Lock }; + Lock.Acquire(); + CxPlatAsyncT Async([](Context* Ctx) { + Ctx->Lock->Acquire(); + Ctx->Event->Set(); + Ctx->Lock->Release(); + }, &Ctx); + TEST_FALSE(Event.WaitTimeout(500)); + Lock.Release(); + TEST_TRUE(Event.WaitTimeout(2000)); + } } void CxPlatTestLockReadWrite() diff --git a/src/test/lib/ThreadTest.cpp b/src/test/lib/ThreadTest.cpp index ccaea7a..383538b 100644 --- a/src/test/lib/ThreadTest.cpp +++ b/src/test/lib/ThreadTest.cpp @@ -64,14 +64,14 @@ void CxPlatTestThreadBasic() void CxPlatTestThreadAsync() { { - CxPlatAsync Async([](void*) -> void { + CxPlatAsync Async([](void*) { // no-op }); } { uint32_t Ctx = 0; - CxPlatAsyncT Async([](uint32_t* Ctx) -> void { + CxPlatAsyncT Async([](uint32_t* Ctx) { *Ctx = 123; }, &Ctx); Async.Wait(); @@ -80,7 +80,7 @@ void CxPlatTestThreadAsync() { CXPLAT_THREAD_ID ThreadId = INITIAL_THREAD_ID_VALUE; - CxPlatAsyncT Async([](CXPLAT_THREAD_ID* Ctx) -> void { + CxPlatAsyncT Async([](CXPLAT_THREAD_ID* Ctx) { *Ctx = CxPlatCurThreadID(); }, &ThreadId); @@ -91,7 +91,7 @@ void CxPlatTestThreadAsync() #if defined(CX_PLATFORM_WINUSER) || defined(CX_PLATFORM_WINKERNEL) { intptr_t Ctx = 0; - CxPlatAsyncT Async([](intptr_t* Ctx) -> void { + CxPlatAsyncT Async([](intptr_t* Ctx) { CxPlatSleep(2000); *Ctx = (intptr_t)(0xdeadbeaf); }, &Ctx); From 3d21466f42e1babd408d43ba639569adf1ffe490 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Sat, 20 Jul 2024 13:26:42 -0400 Subject: [PATCH 6/6] oops --- inc/cxplat.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/inc/cxplat.hpp b/inc/cxplat.hpp index 14dd2af..875eeef 100644 --- a/inc/cxplat.hpp +++ b/inc/cxplat.hpp @@ -63,6 +63,7 @@ struct CxPlatEvent { CxPlatEvent() noexcept { CxPlatEventInitialize(&Handle, FALSE, FALSE); } CxPlatEvent(bool ManualReset) noexcept { CxPlatEventInitialize(&Handle, ManualReset, FALSE); } CxPlatEvent(CXPLAT_EVENT event) noexcept : Handle(event) { } + ~CxPlatEvent() noexcept { CxPlatEventUninitialize(Handle); } operator CXPLAT_EVENT() const noexcept { return Handle; } void Set() { CxPlatEventSet(Handle); } void Reset() { CxPlatEventReset(Handle); }