Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45819 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 11 -------- dlls/ntoskrnl.exe/sync.c | 10 +++++++ include/ddk/wdm.h | 54 +++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 60953dfc1c..c6a10f19d2 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2371,17 +2371,6 @@ void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag ) HeapFree( GetProcessHeap(), 0, ptr ); }
- -/*********************************************************************** - * ExInitializeResourceLite (NTOSKRNL.EXE.@) - */ -NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource) -{ - FIXME( "stub: %p\n", Resource ); - return STATUS_NOT_IMPLEMENTED; -} - - /*********************************************************************** * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 12dacae408..168c6d1642 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -717,3 +717,13 @@ void WINAPI ExReleaseFastMutexUnsafe( FAST_MUTEX *mutex ) if (count < 1) KeSetEvent( &mutex->Event, IO_NO_INCREMENT, FALSE ); } + +/*********************************************************************** + * ExInitializeResourceLite (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI ExInitializeResourceLite( ERESOURCE *resource ) +{ + TRACE("resource %p.\n", resource); + memset(resource, 0, sizeof(*resource)); + return STATUS_SUCCESS; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index e5804c0270..a6536212b6 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -153,12 +153,63 @@ typedef struct _KWAIT_BLOCK { USHORT WaitType; } KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK;
+typedef struct _OWNER_ENTRY +{ + ERESOURCE_THREAD OwnerThread; + union + { + struct + { + ULONG IoPriorityBoosted : 1; + ULONG OwnerReferenced : 1; + ULONG IoQoSPriorityBoosted : 1; + ULONG OwnerCount : 29; + }; + ULONG TableSize; + }; +} OWNER_ENTRY, *POWNER_ENTRY; + +#define ResourceNeverExclusive 0x0010 +#define ResourceReleaseByOtherThread 0x0020 +#define ResourceOwnedExclusive 0x0080 + +typedef struct _ERESOURCE +{ + LIST_ENTRY SystemResourcesList; + OWNER_ENTRY *OwnerTable; + SHORT ActiveCount; + union + { + USHORT Flag; + struct + { + UCHAR ReservedLowFlags; + UCHAR WaiterPriority; + }; + }; + KSEMAPHORE *SharedWaiters; + KEVENT *ExclusiveWaiters; + OWNER_ENTRY OwnerEntry; + ULONG ActiveEntries; + ULONG ContentionCount; + ULONG NumberOfSharedWaiters; + ULONG NumberOfExclusiveWaiters; +#ifdef _WIN64 + void *Reserved2; +#endif + union + { + void *Address; + ULONG_PTR CreatorBackTraceIndex; + }; + KSPIN_LOCK SpinLock; +} ERESOURCE, *PERESOURCE; + typedef struct _IO_TIMER *PIO_TIMER; typedef struct _IO_TIMER_ROUTINE *PIO_TIMER_ROUTINE; typedef struct _ETHREAD *PETHREAD; typedef struct _KTHREAD *PKTHREAD, *PRKTHREAD; typedef struct _EPROCESS *PEPROCESS; -typedef struct _ERESOURCE *PERESOURCE; typedef struct _IO_WORKITEM *PIO_WORKITEM; typedef struct _PAGED_LOOKASIDE_LIST *PPAGED_LOOKASIDE_LIST; typedef struct _OBJECT_TYPE *POBJECT_TYPE; @@ -1469,6 +1520,7 @@ void WINAPI ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); 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); PSLIST_ENTRY WINAPI ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 9 ----- dlls/ntoskrnl.exe/sync.c | 71 ++++++++++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index c6a10f19d2..441bfc57d1 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -3356,15 +3356,6 @@ NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_ return STATUS_SUCCESS; }
-/*********************************************************************** - * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@) - */ -BOOLEAN WINAPI ExAcquireResourceExclusiveLite( PERESOURCE resource, BOOLEAN wait ) -{ - FIXME( ":%p %u stub\n", resource, wait ); - return TRUE; -} - /*********************************************************************** * ExDeleteResourceLite (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 168c6d1642..0c8d02f7dd 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -30,6 +30,7 @@ #include "ddk/wdm.h"
#include "wine/debug.h" +#include "wine/heap.h"
#include "ntoskrnl_private.h"
@@ -718,6 +719,19 @@ void WINAPI ExReleaseFastMutexUnsafe( FAST_MUTEX *mutex ) KeSetEvent( &mutex->Event, IO_NO_INCREMENT, FALSE ); }
+/* Use of the fields of an ERESOURCE structure seems to vary wildly between + * Windows versions. The below implementation uses them as follows: + * + * OwnerTable - contains a list of shared owners, including threads which do + * not currently own the resource + * OwnerTable[i].OwnerThread - shared owner TID + * OwnerTable[i].OwnerCount - recursion count of this shared owner (may be 0) + * OwnerEntry.OwnerThread - the owner TID if exclusively owned + * OwnerEntry.TableSize - the number of entries in OwnerTable, including threads + * which do not currently own the resource + * ActiveEntries - total number of acquisitions (incl. recursive ones) + */ + /*********************************************************************** * ExInitializeResourceLite (NTOSKRNL.EXE.@) */ @@ -727,3 +741,60 @@ NTSTATUS WINAPI ExInitializeResourceLite( ERESOURCE *resource ) memset(resource, 0, sizeof(*resource)); return STATUS_SUCCESS; } + +/*********************************************************************** + * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireResourceExclusiveLite( ERESOURCE *resource, BOOLEAN wait ) +{ + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + /* In order to avoid a race between waiting for the ExclusiveWaiters event + * and grabbing the lock, do not grab the resource if it is unclaimed but + * has waiters; instead queue ourselves. */ + else if (!resource->ActiveEntries && !resource->NumberOfExclusiveWaiters && !resource->NumberOfSharedWaiters) + { + resource->Flag |= ResourceOwnedExclusive; + resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread(); + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + else if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->ExclusiveWaiters) + { + resource->ExclusiveWaiters = heap_alloc( sizeof(*resource->ExclusiveWaiters) ); + KeInitializeEvent( resource->ExclusiveWaiters, SynchronizationEvent, FALSE ); + } + resource->NumberOfExclusiveWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->ExclusiveWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + resource->Flag |= ResourceOwnedExclusive; + resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread(); + resource->ActiveEntries++; + resource->NumberOfExclusiveWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a6536212b6..69916056eb 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1512,6 +1512,7 @@ static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routi
NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG); void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); +BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 82 +++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 508f9e650c..177800a8dc 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -121,7 +121,7 @@ @ stdcall DbgQueryDebugFilterState(long long) @ stub DbgSetDebugFilterState @ stdcall ExAcquireResourceExclusiveLite(ptr long) -@ stub ExAcquireResourceSharedLite +@ stdcall ExAcquireResourceSharedLite(ptr long) @ stub ExAcquireSharedStarveExclusive @ stub ExAcquireSharedWaitForExclusive @ stub ExAllocateFromPagedLookasideList diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 0c8d02f7dd..82667e8510 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -19,6 +19,7 @@ */
#include "config.h" +#include <limits.h> #include <stdarg.h>
#include "ntstatus.h" @@ -742,6 +743,25 @@ NTSTATUS WINAPI ExInitializeResourceLite( ERESOURCE *resource ) return STATUS_SUCCESS; }
+/* Find an existing entry in the shared owner list, or create a new one. */ +static OWNER_ENTRY *resource_get_shared_entry( ERESOURCE *resource, ERESOURCE_THREAD thread ) +{ + ULONG i, count; + + for (i = 0; i < resource->OwnerEntry.TableSize; ++i) + { + if (resource->OwnerTable[i].OwnerThread == thread) + return &resource->OwnerTable[i]; + } + + count = ++resource->OwnerEntry.TableSize; + resource->OwnerTable = heap_realloc(resource->OwnerTable, count * sizeof(*resource->OwnerTable)); + resource->OwnerTable[count - 1].OwnerThread = thread; + resource->OwnerTable[count - 1].OwnerCount = 0; + + return &resource->OwnerTable[count - 1]; +} + /*********************************************************************** * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@) */ @@ -798,3 +818,65 @@ BOOLEAN WINAPI ExAcquireResourceExclusiveLite( ERESOURCE *resource, BOOLEAN wait
return TRUE; } + +/*********************************************************************** + * ExAcquireResourceSharedLite (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireResourceSharedLite( ERESOURCE *resource, BOOLEAN wait ) +{ + OWNER_ENTRY *entry; + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry = resource_get_shared_entry( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); + + if (resource->Flag & ResourceOwnedExclusive) + { + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + /* We own the resource exclusively, so increase recursion. */ + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + } + else if (entry->OwnerCount || !resource->NumberOfExclusiveWaiters) + { + /* Either we already own the resource shared, or there are no exclusive + * owners or waiters, so we can grab it shared. */ + entry->OwnerCount++; + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + + if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->SharedWaiters) + { + resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) ); + KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX ); + } + resource->NumberOfSharedWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->SharedWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry->OwnerCount++; + resource->ActiveEntries++; + resource->NumberOfSharedWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 69916056eb..a153942bf5 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1513,6 +1513,7 @@ static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routi NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG); void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); +BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 64 +++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 177800a8dc..347febb63f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -122,7 +122,7 @@ @ stub DbgSetDebugFilterState @ stdcall ExAcquireResourceExclusiveLite(ptr long) @ stdcall ExAcquireResourceSharedLite(ptr long) -@ stub ExAcquireSharedStarveExclusive +@ stdcall ExAcquireSharedStarveExclusive(ptr long) @ stub ExAcquireSharedWaitForExclusive @ stub ExAllocateFromPagedLookasideList @ stdcall ExAllocatePool(long long) diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 82667e8510..2b362efc82 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -880,3 +880,67 @@ BOOLEAN WINAPI ExAcquireResourceSharedLite( ERESOURCE *resource, BOOLEAN wait )
return TRUE; } + +/*********************************************************************** + * ExAcquireSharedStarveExclusive (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireSharedStarveExclusive( ERESOURCE *resource, BOOLEAN wait ) +{ + OWNER_ENTRY *entry; + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry = resource_get_shared_entry( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); + + if (resource->Flag & ResourceOwnedExclusive) + { + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + } + /* We are starving exclusive waiters, but we cannot steal the resource out + * from under an exclusive waiter who is about to acquire it. (Because of + * locking, and because exclusive waiters are always waked first, this is + * guaranteed to be the case if the resource is unowned and there are + * exclusive waiters.) */ + else if (!(!resource->ActiveEntries && resource->NumberOfExclusiveWaiters)) + { + entry->OwnerCount++; + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + + if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->SharedWaiters) + { + resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) ); + KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX ); + } + resource->NumberOfSharedWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->SharedWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry->OwnerCount++; + resource->ActiveEntries++; + resource->NumberOfSharedWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a153942bf5..8023fda64e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1514,6 +1514,7 @@ NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG); void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); +BOOLEAN WINAPI ExAcquireSharedStarveExclusive(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);
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=50702
Your paranoid android.
=== debian9 (32 bit Chinese:China report) ===
ntoskrnl.exe: driver.c:606: Test failed: got 0 driver.c:632: Test failed: got 0 driver.c:635: Test failed: got 0x102
=== debian9 (64 bit WoW report) ===
ntoskrnl.exe: driver.c:606: Test failed: got 0 ntoskrnl.c:237: Test failed: driver3 should fail to start ntoskrnl.c:238: Test failed: got 183
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 62 +++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 347febb63f..ee26d8b6e2 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -123,7 +123,7 @@ @ stdcall ExAcquireResourceExclusiveLite(ptr long) @ stdcall ExAcquireResourceSharedLite(ptr long) @ stdcall ExAcquireSharedStarveExclusive(ptr long) -@ stub ExAcquireSharedWaitForExclusive +@ stdcall ExAcquireSharedWaitForExclusive(ptr long) @ stub ExAllocateFromPagedLookasideList @ stdcall ExAllocatePool(long long) @ stdcall ExAllocatePoolWithQuota(long long) diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 2b362efc82..e89fddcbba 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -944,3 +944,65 @@ BOOLEAN WINAPI ExAcquireSharedStarveExclusive( ERESOURCE *resource, BOOLEAN wait
return TRUE; } + +/*********************************************************************** + * ExAcquireSharedWaitForExclusive (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireSharedWaitForExclusive( ERESOURCE *resource, BOOLEAN wait ) +{ + OWNER_ENTRY *entry; + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry = resource_get_shared_entry( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); + + if (resource->Flag & ResourceOwnedExclusive) + { + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + /* We own the resource exclusively, so increase recursion. */ + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + } + /* We may only grab the resource if there are no exclusive waiters, even if + * we already own it shared. */ + else if (!resource->NumberOfExclusiveWaiters) + { + entry->OwnerCount++; + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + + if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->SharedWaiters) + { + resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) ); + KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX ); + } + resource->NumberOfSharedWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->SharedWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry->OwnerCount++; + resource->ActiveEntries++; + resource->NumberOfSharedWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 8023fda64e..4609790a66 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1515,6 +1515,7 @@ void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireSharedStarveExclusive(ERESOURCE*,BOOLEAN); +BOOLEAN WINAPI ExAcquireSharedWaitForExclusive(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 8 ----- dlls/ntoskrnl.exe/sync.c | 60 ++++++++++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 441bfc57d1..42498ad412 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -3365,14 +3365,6 @@ NTSTATUS WINAPI ExDeleteResourceLite(PERESOURCE resource) return STATUS_NOT_IMPLEMENTED; }
-/*********************************************************************** - * ExReleaseResourceForThreadLite (NTOSKRNL.EXE.@) - */ -void WINAPI ExReleaseResourceForThreadLite( PERESOURCE resource, ERESOURCE_THREAD tid ) -{ - FIXME( "stub: %p %lu\n", resource, tid ); -} - /*********************************************************************** * KeEnterCriticalRegion (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index e89fddcbba..88c9ea70c7 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1006,3 +1006,63 @@ BOOLEAN WINAPI ExAcquireSharedWaitForExclusive( ERESOURCE *resource, BOOLEAN wai
return TRUE; } + +/*********************************************************************** + * ExReleaseResourceForThreadLite (NTOSKRNL.EXE.@) + */ +void WINAPI ExReleaseResourceForThreadLite( ERESOURCE *resource, ERESOURCE_THREAD thread ) +{ + OWNER_ENTRY *entry; + KIRQL irql; + + TRACE("resource %p, thread %#lx.\n", resource, thread); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + if (resource->Flag & ResourceOwnedExclusive) + { + if (resource->OwnerEntry.OwnerThread == thread) + { + if (!--resource->ActiveEntries) + { + resource->OwnerEntry.OwnerThread = 0; + resource->Flag &= ~ResourceOwnedExclusive; + } + } + else + { + ERR("Trying to release %p for thread %#lx, but resource is exclusively owned by %#lx.\n", + resource, thread, resource->OwnerEntry.OwnerThread); + return; + } + } + else + { + entry = resource_get_shared_entry( resource, thread ); + if (entry->OwnerCount) + { + entry->OwnerCount--; + resource->ActiveEntries--; + } + else + { + ERR("Trying to release %p for thread %#lx, but resource is not owned by that thread.\n", resource, thread); + return; + } + } + + if (!resource->ActiveEntries) + { + if (resource->NumberOfExclusiveWaiters) + { + KeSetEvent( resource->ExclusiveWaiters, IO_NO_INCREMENT, FALSE ); + } + else if (resource->NumberOfSharedWaiters) + { + KeReleaseSemaphore( resource->SharedWaiters, IO_NO_INCREMENT, + resource->NumberOfSharedWaiters, FALSE ); + } + } + + KeReleaseSpinLock( &resource->SpinLock, irql ); +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 4609790a66..1a3f6bbd54 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1529,6 +1529,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*); void WINAPI ExReleaseFastMutexUnsafe(PFAST_MUTEX); +void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD); ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN);
void WINAPI IoAcquireCancelSpinLock(KIRQL*);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 8 -------- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 9 +++++++++ 3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 42498ad412..8b643b4acb 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -4225,14 +4225,6 @@ NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG component, ULONG level) return STATUS_NOT_IMPLEMENTED; }
-/********************************************************************* - * ExReleaseResourceLite (NTOSKRNL.@) - */ -void WINAPI ExReleaseResourceLite(PERESOURCE resource) -{ - FIXME("stub: %p\n", resource); -} - /********************************************************************* * PsGetProcessWow64Process (NTOSKRNL.@) */ diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index ee26d8b6e2..2d1c82663d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -9,7 +9,7 @@ @ stdcall -fastcall -arch=i386 ExInterlockedPushEntrySList (ptr ptr ptr) NTOSKRNL_ExInterlockedPushEntrySList @ stub ExReInitializeRundownProtection @ stdcall -fastcall ExReleaseFastMutexUnsafe(ptr) -@ stdcall ExReleaseResourceLite(ptr) +@ stdcall -fastcall ExReleaseResourceLite(ptr) @ stub ExReleaseRundownProtection @ stub ExReleaseRundownProtectionEx @ stub ExRundownCompleted diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 88c9ea70c7..2ea2e61455 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -1066,3 +1066,12 @@ void WINAPI ExReleaseResourceForThreadLite( ERESOURCE *resource, ERESOURCE_THREA
KeReleaseSpinLock( &resource->SpinLock, irql ); } + +/*********************************************************************** + * ExReleaseResourceLite (NTOSKRNL.EXE.@) + */ +DEFINE_FASTCALL1_WRAPPER( ExReleaseResourceLite ) +void WINAPI ExReleaseResourceLite( ERESOURCE *resource ) +{ + ExReleaseResourceForThreadLite( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); +}
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 9 --------- dlls/ntoskrnl.exe/sync.c | 12 ++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 8b643b4acb..142909e5e2 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -3356,15 +3356,6 @@ NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_ return STATUS_SUCCESS; }
-/*********************************************************************** - * ExDeleteResourceLite (NTOSKRNL.EXE.@) - */ -NTSTATUS WINAPI ExDeleteResourceLite(PERESOURCE resource) -{ - FIXME("(%p): stub\n", resource); - return STATUS_NOT_IMPLEMENTED; -} - /*********************************************************************** * KeEnterCriticalRegion (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 2ea2e61455..c8cae7dd89 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -743,6 +743,18 @@ NTSTATUS WINAPI ExInitializeResourceLite( ERESOURCE *resource ) return STATUS_SUCCESS; }
+/*********************************************************************** + * ExDeleteResourceLite (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI ExDeleteResourceLite( ERESOURCE *resource ) +{ + TRACE("resource %p.\n", resource); + heap_free(resource->OwnerTable); + heap_free(resource->ExclusiveWaiters); + heap_free(resource->SharedWaiters); + return STATUS_SUCCESS; +} + /* Find an existing entry in the shared owner list, or create a new one. */ static OWNER_ENTRY *resource_get_shared_entry( ERESOURCE *resource, ERESOURCE_THREAD thread ) { diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 1a3f6bbd54..41c462f4a7 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1521,6 +1521,7 @@ PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG); PVOID WINAPI ExAllocatePoolWithQuotaTag(POOL_TYPE,SIZE_T,ULONG); void WINAPI ExDeleteNPagedLookasideList(PNPAGED_LOOKASIDE_LIST); +NTSTATUS WINAPI ExDeleteResourceLite(ERESOURCE*); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT);