Files
nt-lite/code/kernel/ke_event.c
T
2026-04-30 23:52:46 +02:00

73 lines
2.3 KiB
C

// ke_event.c - synchronisation events
#include "ke_event.h"
#include "ke_thread.h"
#include "ke_sched.h"
#include "ob_object.h"
static void EventDestroy(OBJECT* obj) { (void)obj; }
KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) {
if (!out) return STATUS_INVALID_PARAMETER;
EVENT* e = (EVENT *)ObAllocateObject(ObjectTypeEvent, sizeof(EVENT));
if (!e) return STATUS_NO_MEMORY;
e->Header.Destroy = EventDestroy;
e->Lock = (SPINLOCK)SPINLOCK_INIT;
e->Type = type;
e->Signaled = initialState ? 1 : 0;
LIST_INIT(&e->WaitList);
*out = e;
return STATUS_SUCCESS;
}
void KeSignalEvent(EVENT* event) {
if (!event) return;
KeAcquireSpinlock(&event->Lock);
if (event->Type == EventManualReset) {
// Wake all waiters.
event->Signaled = 1;
while (!LIST_IS_EMPTY(&event->WaitList)) {
LIST_ENTRY* node = ListPopHead(&event->WaitList);
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
KeReleaseSpinlock(&event->Lock);
KeUnblockThread(t);
KeAcquireSpinlock(&event->Lock);
}
} else {
// Auto-reset: wake one waiter or set the flag for the next waiter.
if (!LIST_IS_EMPTY(&event->WaitList)) {
LIST_ENTRY* node = ListPopHead(&event->WaitList);
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
KeReleaseSpinlock(&event->Lock);
KeUnblockThread(t);
return;
}
event->Signaled = 1;
}
KeReleaseSpinlock(&event->Lock);
}
void KeClearEvent(EVENT* event) {
if (!event) return;
KeAcquireSpinlock(&event->Lock);
event->Signaled = 0;
KeReleaseSpinlock(&event->Lock);
}
KSTATUS KeWaitForEvent(EVENT* event) {
if (!event) return STATUS_INVALID_PARAMETER;
THREAD* self = KeCurrentThread();
for (;;) {
KeAcquireSpinlock(&event->Lock);
if (event->Signaled) {
if (event->Type == EventAutoReset) event->Signaled = 0;
KeReleaseSpinlock(&event->Lock);
return STATUS_SUCCESS;
}
ListInsertTail(&event->WaitList, &self->SchedulerLink);
KeReleaseSpinlock(&event->Lock);
KeBlockThread(self, &event->Header);
}
}