Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 19 +++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 2d1c82663d..bdf2a4463c 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -146,7 +146,7 @@ @ stub ExFreeToPagedLookasideList @ stub ExGetCurrentProcessorCounts @ stub ExGetCurrentProcessorCpuUsage -@ stub ExGetExclusiveWaiterCount +@ stdcall ExGetExclusiveWaiterCount(ptr) @ stub ExGetPreviousMode @ stub ExGetSharedWaiterCount @ stdcall ExInitializeNPagedLookasideList(ptr ptr ptr long long long long) diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index c8cae7dd89..823ff2b587 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1087,3 +1087,22 @@ void WINAPI ExReleaseResourceLite( ERESOURCE *resource ) { ExReleaseResourceForThreadLite( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); } + +/*********************************************************************** + * ExGetExclusiveWaiterCount (NTOSKRNL.EXE.@) + */ +ULONG WINAPI ExGetExclusiveWaiterCount( ERESOURCE *resource ) +{ + ULONG count; + KIRQL irql; + + TRACE("resource %p.\n", resource); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + count = resource->NumberOfExclusiveWaiters; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return count; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 41c462f4a7..241f6d695e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1524,6 +1524,7 @@ void WINAPI ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST); NTSTATUS WINAPI ExDeleteResourceLite(ERESOURCE*); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); +ULONG WINAPI ExGetExclusiveWaiterCount(ERESOURCE*); void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT); NTSTATUS WINAPI ExInitializeResourceLite(ERESOURCE*); PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 19 +++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index bdf2a4463c..3324b3b6d8 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -148,7 +148,7 @@ @ stub ExGetCurrentProcessorCpuUsage @ stdcall ExGetExclusiveWaiterCount(ptr) @ stub ExGetPreviousMode -@ stub ExGetSharedWaiterCount +@ stdcall ExGetSharedWaiterCount(ptr) @ stdcall ExInitializeNPagedLookasideList(ptr ptr ptr long long long long) @ stdcall ExInitializePagedLookasideList(ptr ptr ptr long long long long) @ stdcall ExInitializeResourceLite(ptr) diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 823ff2b587..7009c4cfec 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1106,3 +1106,22 @@ ULONG WINAPI ExGetExclusiveWaiterCount( ERESOURCE *resource )
return count; } + +/*********************************************************************** + * ExGetSharedWaiterCount (NTOSKRNL.EXE.@) + */ +ULONG WINAPI ExGetSharedWaiterCount( ERESOURCE *resource ) +{ + ULONG count; + KIRQL irql; + + TRACE("resource %p.\n", resource); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + count = resource->NumberOfSharedWaiters; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return count; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 241f6d695e..a0219c4c1e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1525,6 +1525,7 @@ NTSTATUS WINAPI ExDeleteResourceLite(ERESOURCE*); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); ULONG WINAPI ExGetExclusiveWaiterCount(ERESOURCE*); +ULONG WINAPI ExGetSharedWaiterCount(ERESOURCE*); void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT); NTSTATUS WINAPI ExInitializeResourceLite(ERESOURCE*); PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 19 +++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 3324b3b6d8..d3e6070149 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -165,7 +165,7 @@ @ stub ExInterlockedPushEntryList @ stdcall ExInterlockedRemoveHeadList(ptr ptr) @ stub ExIsProcessorFeaturePresent -@ stub ExIsResourceAcquiredExclusiveLite +@ stdcall ExIsResourceAcquiredExclusiveLite(ptr) @ stub ExIsResourceAcquiredSharedLite @ stdcall ExLocalTimeToSystemTime(ptr ptr) RtlLocalTimeToSystemTime @ stub ExNotifyCallback diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 7009c4cfec..94b9778602 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1125,3 +1125,22 @@ ULONG WINAPI ExGetSharedWaiterCount( ERESOURCE *resource )
return count; } + +/*********************************************************************** + * ExIsResourceAcquiredExclusiveLite (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite( ERESOURCE *resource ) +{ + BOOLEAN ret; + KIRQL irql; + + TRACE("resource %p.\n", resource); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + ret = (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()); + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return ret; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a0219c4c1e..5a84602d43 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1531,6 +1531,7 @@ NTSTATUS WINAPI ExInitializeResourceLite(ERESOURCE*); PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK); PSLIST_ENTRY WINAPI ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*); +BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite(ERESOURCE*); void WINAPI ExReleaseFastMutexUnsafe(PFAST_MUTEX); void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD); ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 25 +++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index d3e6070149..ab952e528b 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -166,7 +166,7 @@ @ stdcall ExInterlockedRemoveHeadList(ptr ptr) @ stub ExIsProcessorFeaturePresent @ stdcall ExIsResourceAcquiredExclusiveLite(ptr) -@ stub ExIsResourceAcquiredSharedLite +@ stdcall ExIsResourceAcquiredSharedLite(ptr) @ stdcall ExLocalTimeToSystemTime(ptr ptr) RtlLocalTimeToSystemTime @ stub ExNotifyCallback @ stub ExQueryPoolBlockSize diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 94b9778602..fbe9dbe9da 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1144,3 +1144,28 @@ BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite( ERESOURCE *resource )
return ret; } + +/*********************************************************************** + * ExIsResourceAcquiredSharedLite (NTOSKRNL.EXE.@) + */ +ULONG WINAPI ExIsResourceAcquiredSharedLite( ERESOURCE *resource ) +{ + ULONG ret; + KIRQL irql; + + TRACE("resource %p.\n", resource); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + ret = resource->ActiveEntries; + else + { + OWNER_ENTRY *entry = resource_get_shared_entry( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); + ret = entry->OwnerCount; + } + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return ret; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 5a84602d43..dae83afb2e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1532,6 +1532,7 @@ PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK); PSLIST_ENTRY WINAPI ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*); BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite(ERESOURCE*); +ULONG WINAPI ExIsResourceAcquiredSharedLite(ERESOURCE*); void WINAPI ExReleaseFastMutexUnsafe(PFAST_MUTEX); void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD); ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/driver.c | 311 ++++++++++++++++++++++++++++++- include/ddk/wdm.h | 2 + 2 files changed, 312 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 81baffa7cc..3796ee5921 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -322,7 +322,14 @@ todo_wine ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); }
-static void run_thread(PKSTART_ROUTINE proc, void *arg) +static void sleep(void) +{ + LARGE_INTEGER timeout; + timeout.QuadPart = -20 * 10000; + KeDelayExecutionThread( KernelMode, FALSE, &timeout ); +} + +static HANDLE create_thread(PKSTART_ROUTINE proc, void *arg) { OBJECT_ATTRIBUTES attr = {0}; HANDLE thread; @@ -333,12 +340,25 @@ static void run_thread(PKSTART_ROUTINE proc, void *arg) ret = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, &attr, NULL, NULL, proc, arg); ok(!ret, "got %#x\n", ret);
+ return thread; +} + +static void join_thread(HANDLE thread) +{ + NTSTATUS ret; + ret = ZwWaitForSingleObject(thread, FALSE, NULL); ok(!ret, "got %#x\n", ret); ret = ZwClose(thread); ok(!ret, "got %#x\n", ret); }
+static void run_thread(PKSTART_ROUTINE proc, void *arg) +{ + HANDLE thread = create_thread(proc, arg); + join_thread(thread); +} + static KMUTEX test_mutex;
static void WINAPI mutex_thread(void *arg) @@ -853,6 +873,294 @@ static void test_ob_reference(const WCHAR *test_path) ok(!status, "ZwClose failed: %#x\n", status); }
+static void check_resource_(int line, ERESOURCE *resource, ULONG exclusive_waiters, + ULONG shared_waiters, BOOLEAN exclusive, ULONG shared_count) +{ + BOOLEAN ret; + ULONG count; + + count = ExGetExclusiveWaiterCount(resource); + ok_(__FILE__, line, count == exclusive_waiters, + "expected %u exclusive waiters, got %u\n", exclusive_waiters, count); + count = ExGetSharedWaiterCount(resource); + ok_(__FILE__, line, count == shared_waiters, + "expected %u shared waiters, got %u\n", shared_waiters, count); + ret = ExIsResourceAcquiredExclusiveLite(resource); + ok_(__FILE__, line, ret == exclusive, + "expected exclusive %u, got %u\n", exclusive, ret); + count = ExIsResourceAcquiredSharedLite(resource); + ok_(__FILE__, line, count == shared_count, + "expected shared %u, got %u\n", shared_count, count); +} +#define check_resource(a,b,c,d,e) check_resource_(__LINE__,a,b,c,d,e) + +static KEVENT resource_shared_ready, resource_shared_done, resource_exclusive_ready, resource_exclusive_done; + +static void WINAPI resource_shared_thread(void *arg) +{ + ERESOURCE *resource = arg; + BOOLEAN ret; + + check_resource(resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceSharedLite(resource, TRUE); + ok(ret == TRUE, "got ret %u\n", ret); + + check_resource(resource, 0, 0, FALSE, 1); + + KeSetEvent(&resource_shared_ready, IO_NO_INCREMENT, FALSE); + KeWaitForSingleObject(&resource_shared_done, Executive, KernelMode, FALSE, NULL); + + ExReleaseResourceForThreadLite(resource, (ULONG_PTR)PsGetCurrentThread()); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + +static void WINAPI resource_exclusive_thread(void *arg) +{ + ERESOURCE *resource = arg; + BOOLEAN ret; + + check_resource(resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceExclusiveLite(resource, TRUE); + ok(ret == TRUE, "got ret %u\n", ret); + + check_resource(resource, 0, 0, TRUE, 1); + + KeSetEvent(&resource_exclusive_ready, IO_NO_INCREMENT, FALSE); + KeWaitForSingleObject(&resource_exclusive_done, Executive, KernelMode, FALSE, NULL); + + ExReleaseResourceForThreadLite(resource, (ULONG_PTR)PsGetCurrentThread()); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + +static void test_resource(void) +{ + ERESOURCE resource; + NTSTATUS status; + BOOLEAN ret; + HANDLE thread, thread2; + + memset(&resource, 0xcc, sizeof(resource)); + + status = ExInitializeResourceLite(&resource); + ok(status == STATUS_SUCCESS, "got status %#x\n", status); + check_resource(&resource, 0, 0, FALSE, 0); + + KeEnterCriticalRegion(); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, TRUE, 1); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, TRUE, 2); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, TRUE, 3); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, TRUE, 2); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, TRUE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 2); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 2); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedStarveExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedWaitForExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */ + + KeInitializeEvent(&resource_shared_ready, SynchronizationEvent, FALSE); + KeInitializeEvent(&resource_shared_done, SynchronizationEvent, FALSE); + thread = create_thread(resource_shared_thread, &resource); + KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedStarveExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedWaitForExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + check_resource(&resource, 0, 0, FALSE, 0); + + KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE); + join_thread(thread); + check_resource(&resource, 0, 0, FALSE, 0); + + /* Acquire the resource as exclusive, and then spawn a shared thread. */ + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, TRUE, 1); + + thread = create_thread(resource_shared_thread, &resource); + sleep(); + check_resource(&resource, 0, 1, TRUE, 1); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 1, TRUE, 2); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL); + KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE); + join_thread(thread); + check_resource(&resource, 0, 0, FALSE, 0); + + /* Do not acquire the resource ourselves, but spawn an exclusive thread holding it. */ + + KeInitializeEvent(&resource_exclusive_ready, SynchronizationEvent, FALSE); + KeInitializeEvent(&resource_exclusive_done, SynchronizationEvent, FALSE); + thread = create_thread(resource_exclusive_thread, &resource); + KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedStarveExclusive(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 0); + + ret = ExAcquireSharedWaitForExclusive(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 0); + + KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE); + join_thread(thread); + check_resource(&resource, 0, 0, FALSE, 0); + + /* Acquire the resource as shared, and then spawn an exclusive waiter. */ + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 0, 0, FALSE, 1); + + thread = create_thread(resource_exclusive_thread, &resource); + sleep(); + check_resource(&resource, 1, 0, FALSE, 1); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 2); + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + + ret = ExAcquireSharedStarveExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 2); + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + + ret = ExAcquireSharedWaitForExclusive(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 1); + + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL); + KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE); + join_thread(thread); + check_resource(&resource, 0, 0, FALSE, 0); + + /* Spawn a shared and then exclusive waiter. */ + + KeInitializeEvent(&resource_shared_ready, SynchronizationEvent, FALSE); + KeInitializeEvent(&resource_shared_done, SynchronizationEvent, FALSE); + thread = create_thread(resource_shared_thread, &resource); + KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL); + check_resource(&resource, 0, 0, FALSE, 0); + + thread2 = create_thread(resource_exclusive_thread, &resource); + sleep(); + check_resource(&resource, 1, 0, FALSE, 0); + + ret = ExAcquireResourceExclusiveLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 0); + + ret = ExAcquireResourceSharedLite(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 0); + + ret = ExAcquireSharedStarveExclusive(&resource, FALSE); + ok(ret == TRUE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 1); + ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread()); + + ret = ExAcquireSharedWaitForExclusive(&resource, FALSE); + ok(ret == FALSE, "got ret %u\n", ret); + check_resource(&resource, 1, 0, FALSE, 0); + + KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE); + join_thread(thread); + KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL); + KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE); + join_thread(thread2); + check_resource(&resource, 0, 0, FALSE, 0); + + KeLeaveCriticalRegion(); + + status = ExDeleteResourceLite(&resource); + ok(status == STATUS_SUCCESS, "got status %#x\n", status); +} + static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -895,6 +1203,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_stack_callout(); test_lookaside_list(); test_ob_reference(test_input->path); + test_resource();
/* print process report */ if (winetest_debug) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index dae83afb2e..0faf5ecd47 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1580,6 +1580,7 @@ void WINAPI KeAcquireSpinLockAtDpcLevel(KSPIN_LOCK*); BOOLEAN WINAPI KeCancelTimer(KTIMER*); void WINAPI KeClearEvent(PRKEVENT); NTSTATUS WINAPI KeDelayExecutionThread(KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*); +void WINAPI KeEnterCriticalRegion(void); PKTHREAD WINAPI KeGetCurrentThread(void); void WINAPI KeInitializeEvent(PRKEVENT,EVENT_TYPE,BOOLEAN); void WINAPI KeInitializeMutex(PRKMUTEX,ULONG); @@ -1587,6 +1588,7 @@ void WINAPI KeInitializeSemaphore(PRKSEMAPHORE,LONG,LONG); void WINAPI KeInitializeSpinLock(KSPIN_LOCK*); void WINAPI KeInitializeTimerEx(PKTIMER,TIMER_TYPE); void WINAPI KeInitializeTimer(KTIMER*); +void WINAPI KeLeaveCriticalRegion(void); void WINAPI KeQuerySystemTime(LARGE_INTEGER*); void WINAPI KeQueryTickCount(LARGE_INTEGER*); ULONG WINAPI KeQueryTimeIncrement(void);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=50780
Your paranoid android.
=== debian9 (64 bit WoW report) ===
ntoskrnl.exe: ntoskrnl.c:237: Test failed: driver3 should fail to start ntoskrnl.c:238: Test failed: got 183