[PATCH 2/6] ntoskrnl.exe: Implement KeReleaseSemaphore() and waiting on semaphores.
Zebediah Figura
z.figura12 at gmail.com
Mon Nov 26 19:39:17 CST 2018
Signed-off-by: Zebediah Figura <z.figura12 at 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)
--
2.14.1
More information about the wine-devel
mailing list