ntoskrnl.exe: Implement KeReleaseSemaphore() and waiting on semaphores.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2018-11-26 19:39:17 -06:00 committed by Alexandre Julliard
parent 8589d094ff
commit 4824d7217b
3 changed files with 95 additions and 11 deletions

View File

@ -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.@)
*/

View File

@ -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;
}

View File

@ -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)