Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 11 ------- dlls/ntoskrnl.exe/sync.c | 31 +++++++++++++++++++ dlls/ntoskrnl.exe/tests/driver.c | 64 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 11 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 07e9104498..d0e77c5df7 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2400,17 +2400,6 @@ void WINAPI KeQueryTickCount( LARGE_INTEGER *count ) }
-/*********************************************************************** - * KeReleaseSemaphore (NTOSKRNL.EXE.@) - */ -LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE Semaphore, KPRIORITY Increment, - LONG Adjustment, BOOLEAN Wait ) -{ - FIXME("(%p %d %d %d) stub\n", Semaphore, Increment, Adjustment, Wait ); - return 0; -} - - /*********************************************************************** * KeQueryTimeIncrement (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 2190faa81f..77178462f5 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -81,6 +81,13 @@ 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_SEMAPHORE: + { + KSEMAPHORE *semaphore = CONTAINING_RECORD(objs[i], KSEMAPHORE, Header); + objs[i]->WaitListHead.Blink = CreateSemaphoreW( NULL, + semaphore->Header.SignalState, semaphore->Limit, NULL ); + break; + } } }
@@ -100,6 +107,9 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[], case TYPE_AUTO_EVENT: objs[i]->SignalState = FALSE; break; + case TYPE_SEMAPHORE: + --objs[i]->SignalState; + break; } }
@@ -187,3 +197,24 @@ void WINAPI KeInitializeSemaphore( PRKSEMAPHORE semaphore, LONG count, LONG limi semaphore->Header.WaitListHead.Flink = NULL; semaphore->Limit = limit; } + +/*********************************************************************** + * KeReleaseSemaphore (NTOSKRNL.EXE.@) + */ +LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE semaphore, KPRIORITY increment, + LONG count, BOOLEAN wait ) +{ + HANDLE handle = semaphore->Header.WaitListHead.Blink; + LONG ret; + + TRACE("semaphore %p, increment %d, count %d, wait %u.\n", + semaphore, increment, count, wait); + + EnterCriticalSection( &sync_cs ); + ret = InterlockedExchangeAdd( &semaphore->Header.SignalState, count ); + if (handle) + ReleaseSemaphore( handle, count, NULL ); + LeaveCriticalSection( &sync_cs ); + + return ret; +} diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 07a0adba60..852a726413 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -228,9 +228,11 @@ static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, UL
static void test_sync(void) { + KSEMAPHORE semaphore, semaphore2; KEVENT manual_event, auto_event; void *objs[2]; NTSTATUS ret; + int i;
KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
@@ -323,6 +325,68 @@ static void test_sync(void)
ret = wait_multiple(2, objs, WaitAny, 0); ok(ret == 1, "got %#x\n", ret); + + /* test semaphores */ + KeInitializeSemaphore(&semaphore, 0, 5); + + ret = wait_single(&semaphore, 0); + ok(ret == STATUS_TIMEOUT, "got %u\n", ret); + + ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE); + ok(ret == 0, "got prev %d\n", ret); + + ret = KeReleaseSemaphore(&semaphore, 0, 2, FALSE); + ok(ret == 1, "got prev %d\n", ret); + + ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE); + ok(ret == 3, "got prev %d\n", ret); + + for (i = 0; i < 4; i++) + { + ret = wait_single(&semaphore, 0); + ok(ret == 0, "got %#x\n", ret); + } + + ret = wait_single(&semaphore, 0); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + + KeInitializeSemaphore(&semaphore2, 3, 5); + + ret = KeReleaseSemaphore(&semaphore2, 0, 1, FALSE); + ok(ret == 3, "got prev %d\n", ret); + + for (i = 0; i < 4; i++) + { + ret = wait_single(&semaphore2, 0); + ok(ret == 0, "got %#x\n", ret); + } + + objs[0] = &semaphore; + objs[1] = &semaphore2; + + ret = wait_multiple(2, objs, WaitAny, 0); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + + KeReleaseSemaphore(&semaphore, 0, 1, FALSE); + KeReleaseSemaphore(&semaphore2, 0, 1, FALSE); + + ret = wait_multiple(2, objs, WaitAny, 0); + ok(ret == 0, "got %#x\n", ret); + + ret = wait_multiple(2, objs, WaitAny, 0); + ok(ret == 1, "got %#x\n", ret); + + ret = wait_multiple(2, objs, WaitAny, 0); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + + KeReleaseSemaphore(&semaphore, 0, 1, FALSE); + KeReleaseSemaphore(&semaphore2, 0, 1, FALSE); + + ret = wait_multiple(2, objs, WaitAll, 0); + ok(ret == 0, "got %#x\n", ret); + + ret = wait_multiple(2, objs, WaitAny, 0); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); }
static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)