ntoskrnl.exe: Implement KeReleaseMutex() and waiting on mutexes.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e3223f30aa
commit
1aaabb781b
|
@ -2288,16 +2288,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.@)
|
||||
*/
|
||||
|
|
|
@ -1404,7 +1404,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()
|
||||
|
|
|
@ -82,6 +82,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);
|
||||
|
@ -108,6 +111,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;
|
||||
|
@ -116,8 +120,24 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
|
|||
|
||||
if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
|
||||
{
|
||||
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:
|
||||
/* Native will panic if a mutex is destroyed while held, so we
|
||||
* don't have to worry about leaking the handle here. */
|
||||
if (objs[i]->SignalState == 1)
|
||||
{
|
||||
CloseHandle(objs[i]->WaitListHead.Blink);
|
||||
objs[i]->WaitListHead.Blink = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &sync_cs );
|
||||
|
@ -232,3 +252,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;
|
||||
}
|
||||
|
|
|
@ -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; /* needed to be accessible from system threads */
|
||||
ZwOpenFile(&okfile, FILE_APPEND_DATA, &attr, &io, 0, 0);
|
||||
|
||||
test_currentprocess();
|
||||
|
|
Loading…
Reference in New Issue