mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
215 lines
7.4 KiB
Diff
215 lines
7.4 KiB
Diff
|
From 7505150045f3ce4cd805e863913289156322b41d Mon Sep 17 00:00:00 2001
|
||
|
From: Zebediah Figura <z.figura12@gmail.com>
|
||
|
Date: Sun, 19 Aug 2018 21:43:37 -0500
|
||
|
Subject: [PATCH 11/17] ntoskrnl.exe: Implement KeReleaseMutex() and waiting on
|
||
|
mutexes.
|
||
|
|
||
|
We can get away with storing the mutex object in the KMUTEX for as long as
|
||
|
it's held, since on Windows it's illegal to destroy a mutex until it's
|
||
|
released.
|
||
|
|
||
|
Setting the flag OBJ_KERNEL_HANDLE on okfile is necessary to allow it to be
|
||
|
written to by system threads.
|
||
|
|
||
|
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||
|
---
|
||
|
dlls/ntoskrnl.exe/ntoskrnl.c | 10 -------
|
||
|
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +-
|
||
|
dlls/ntoskrnl.exe/sync.c | 44 ++++++++++++++++++++++++++--
|
||
|
dlls/ntoskrnl.exe/tests/driver.c | 58 +++++++++++++++++++++++++++++++++++++
|
||
|
4 files changed, 101 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
|
||
|
index 920fb74..cc88100 100644
|
||
|
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
|
||
|
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
|
||
|
@@ -2096,16 +2096,6 @@ NTSTATUS WINAPI KeWaitForMutexObject(PRKMUTEX Mutex, KWAIT_REASON WaitReason, KP
|
||
|
}
|
||
|
|
||
|
|
||
|
- /***********************************************************************
|
||
|
- * KeReleaseMutex (NTOSKRNL.EXE.@)
|
||
|
- */
|
||
|
-LONG WINAPI KeReleaseMutex(PRKMUTEX Mutex, BOOLEAN Wait)
|
||
|
-{
|
||
|
- FIXME( "stub: %p, %d\n", Mutex, Wait );
|
||
|
- return STATUS_NOT_IMPLEMENTED;
|
||
|
-}
|
||
|
-
|
||
|
-
|
||
|
/***********************************************************************
|
||
|
* KeInitializeSpinLock (NTOSKRNL.EXE.@)
|
||
|
*/
|
||
|
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
|
||
|
index 422d575..f089f41 100644
|
||
|
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
|
||
|
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
|
||
|
@@ -1402,7 +1402,7 @@
|
||
|
@ stdcall -private ZwUnloadKey(ptr) NtUnloadKey
|
||
|
@ stdcall -private ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection
|
||
|
@ stdcall -private ZwWaitForMultipleObjects(long ptr long long ptr) NtWaitForMultipleObjects
|
||
|
-@ stdcall -private ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject
|
||
|
+@ stdcall ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject
|
||
|
@ stdcall ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile
|
||
|
@ stdcall -private ZwYieldExecution() NtYieldExecution
|
||
|
@ stdcall -private -arch=arm,x86_64 -norelay __chkstk()
|
||
|
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
|
||
|
index 7535ae8..a038a07 100644
|
||
|
--- a/dlls/ntoskrnl.exe/sync.c
|
||
|
+++ b/dlls/ntoskrnl.exe/sync.c
|
||
|
@@ -84,6 +84,9 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
||
|
case TYPE_AUTO_EVENT:
|
||
|
objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL );
|
||
|
break;
|
||
|
+ case TYPE_MUTEX:
|
||
|
+ objs[i]->WaitListHead.Blink = CreateMutexW( NULL, FALSE, NULL );
|
||
|
+ break;
|
||
|
case TYPE_SEMAPHORE:
|
||
|
{
|
||
|
KSEMAPHORE *semaphore = CONTAINING_RECORD(objs[i], KSEMAPHORE, Header);
|
||
|
@@ -110,6 +113,7 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
||
|
case TYPE_AUTO_EVENT:
|
||
|
objs[i]->SignalState = FALSE;
|
||
|
break;
|
||
|
+ case TYPE_MUTEX:
|
||
|
case TYPE_SEMAPHORE:
|
||
|
--objs[i]->SignalState;
|
||
|
break;
|
||
|
@@ -118,8 +122,22 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
||
|
|
||
|
if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
|
||
|
{
|
||
|
- CloseHandle(objs[i]->WaitListHead.Blink);
|
||
|
- objs[i]->WaitListHead.Blink = NULL;
|
||
|
+ switch (objs[i]->Type)
|
||
|
+ {
|
||
|
+ case TYPE_MANUAL_EVENT:
|
||
|
+ case TYPE_AUTO_EVENT:
|
||
|
+ case TYPE_SEMAPHORE:
|
||
|
+ CloseHandle(objs[i]->WaitListHead.Blink);
|
||
|
+ objs[i]->WaitListHead.Blink = NULL;
|
||
|
+ break;
|
||
|
+ case TYPE_MUTEX:
|
||
|
+ if (objs[i]->SignalState == 1)
|
||
|
+ {
|
||
|
+ CloseHandle(objs[i]->WaitListHead.Blink);
|
||
|
+ objs[i]->WaitListHead.Blink = NULL;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
LeaveCriticalSection( &sync_cs );
|
||
|
@@ -242,3 +260,25 @@ void WINAPI KeInitializeMutex( PRKMUTEX mutex, ULONG level )
|
||
|
mutex->Header.WaitListHead.Blink = NULL;
|
||
|
mutex->Header.WaitListHead.Flink = NULL;
|
||
|
}
|
||
|
+
|
||
|
+/***********************************************************************
|
||
|
+ * KeReleaseMutex (NTOSKRNL.EXE.@)
|
||
|
+ */
|
||
|
+LONG WINAPI KeReleaseMutex( PRKMUTEX mutex, BOOLEAN wait )
|
||
|
+{
|
||
|
+ HANDLE handle = mutex->Header.WaitListHead.Blink;
|
||
|
+ LONG ret;
|
||
|
+
|
||
|
+ TRACE("mutex %p, wait %u.\n", mutex, wait);
|
||
|
+
|
||
|
+ EnterCriticalSection( &sync_cs );
|
||
|
+ ret = mutex->Header.SignalState++;
|
||
|
+ if (!ret && !mutex->Header.WaitListHead.Flink)
|
||
|
+ {
|
||
|
+ CloseHandle( handle );
|
||
|
+ mutex->Header.WaitListHead.Blink = NULL;
|
||
|
+ }
|
||
|
+ LeaveCriticalSection( &sync_cs );
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
|
||
|
index 852a726..e758e3f 100644
|
||
|
--- a/dlls/ntoskrnl.exe/tests/driver.c
|
||
|
+++ b/dlls/ntoskrnl.exe/tests/driver.c
|
||
|
@@ -226,6 +226,36 @@ static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, UL
|
||
|
return KeWaitForMultipleObjects(count, objs, wait_type, Executive, KernelMode, FALSE, &integer, NULL);
|
||
|
}
|
||
|
|
||
|
+static void run_thread(PKSTART_ROUTINE proc, void *arg)
|
||
|
+{
|
||
|
+ OBJECT_ATTRIBUTES attr = {0};
|
||
|
+ HANDLE thread;
|
||
|
+ NTSTATUS ret;
|
||
|
+
|
||
|
+ attr.Length = sizeof(attr);
|
||
|
+ attr.Attributes = OBJ_KERNEL_HANDLE;
|
||
|
+ ret = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, &attr, NULL, NULL, proc, arg);
|
||
|
+ ok(!ret, "got %#x\n", ret);
|
||
|
+
|
||
|
+ ret = ZwWaitForSingleObject(thread, FALSE, NULL);
|
||
|
+ ok(!ret, "got %#x\n", ret);
|
||
|
+ ret = ZwClose(thread);
|
||
|
+ ok(!ret, "got %#x\n", ret);
|
||
|
+}
|
||
|
+
|
||
|
+static KMUTEX test_mutex;
|
||
|
+
|
||
|
+static void WINAPI mutex_thread(void *arg)
|
||
|
+{
|
||
|
+ NTSTATUS ret, expect = (NTSTATUS)(DWORD_PTR)arg;
|
||
|
+
|
||
|
+ ret = wait_single(&test_mutex, 0);
|
||
|
+ ok(ret == expect, "expected %#x, got %#x\n", expect, ret);
|
||
|
+
|
||
|
+ if (!ret) KeReleaseMutex(&test_mutex, FALSE);
|
||
|
+ PsTerminateSystemThread(STATUS_SUCCESS);
|
||
|
+}
|
||
|
+
|
||
|
static void test_sync(void)
|
||
|
{
|
||
|
KSEMAPHORE semaphore, semaphore2;
|
||
|
@@ -387,6 +417,33 @@ static void test_sync(void)
|
||
|
|
||
|
ret = wait_multiple(2, objs, WaitAny, 0);
|
||
|
ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
|
||
|
+
|
||
|
+ /* test mutexes */
|
||
|
+ KeInitializeMutex(&test_mutex, 0);
|
||
|
+
|
||
|
+ for (i = 0; i < 10; i++)
|
||
|
+ {
|
||
|
+ ret = wait_single(&test_mutex, 0);
|
||
|
+ ok(ret == 0, "got %#x\n", ret);
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < 10; i++)
|
||
|
+ {
|
||
|
+ ret = KeReleaseMutex(&test_mutex, FALSE);
|
||
|
+ ok(ret == i - 9, "expected %d, got %d\n", i - 9, ret);
|
||
|
+ }
|
||
|
+
|
||
|
+ run_thread(mutex_thread, (void *)0);
|
||
|
+
|
||
|
+ ret = wait_single(&test_mutex, 0);
|
||
|
+ ok(ret == 0, "got %#x\n", ret);
|
||
|
+
|
||
|
+ run_thread(mutex_thread, (void *)STATUS_TIMEOUT);
|
||
|
+
|
||
|
+ ret = KeReleaseMutex(&test_mutex, 0);
|
||
|
+ ok(ret == 0, "got %#x\n", ret);
|
||
|
+
|
||
|
+ run_thread(mutex_thread, (void *)0);
|
||
|
}
|
||
|
|
||
|
static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
|
||
|
@@ -410,6 +467,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
|
||
|
winetest_debug = test_input->winetest_debug;
|
||
|
winetest_report_success = test_input->winetest_report_success;
|
||
|
attr.ObjectName = &pathU;
|
||
|
+ attr.Attributes = OBJ_KERNEL_HANDLE;
|
||
|
ZwOpenFile(&okfile, FILE_APPEND_DATA, &attr, &io, 0, 0);
|
||
|
|
||
|
test_currentprocess();
|
||
|
--
|
||
|
2.7.4
|
||
|
|