implement proper IRQL, DPCs, kernel and user APCs, alertable waits, async file I/O with cancellation, trap frames, selftests, a real driver/device model, native async FAT32, VFAT dotfile fixes, syscall ABI cleanup, async_apc and async_cancel tests, POSIX multi-volume paths, and pimp the readme.
This commit is contained in:
1 parent
f5fd7bdd75
commit
529f816166
75 files changed
+9969
-5675
No files matched your search
+81
-71
@@ -1,71 +1,81 @@
|
||||
// ke_event.c - synchronisation events
|
||||
#include <stdbool.h>
|
||||
#include <ke_event.h>
|
||||
#include <ke_thread.h>
|
||||
#include <ke_sched.h>
|
||||
#include <ob_object.h>
|
||||
|
||||
static void EventDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
__declspec(dllexport) 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;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void KeSignalEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
|
||||
if (event->Type == EventManualReset) {
|
||||
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, flags);
|
||||
KeUnblockThread(t);
|
||||
flags = KeAcquireSpinlock(&event->Lock);
|
||||
}
|
||||
} else {
|
||||
event->Signaled = 1;
|
||||
if (!LIST_IS_EMPTY(&event->WaitList)) {
|
||||
LIST_ENTRY* node = ListPopHead(&event->WaitList);
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeUnblockThread(t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void KeClearEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event) {
|
||||
if (!event) return STATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
|
||||
while (true) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
if (event->Signaled) {
|
||||
if (event->Type == EventAutoReset) event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
ListInsertTail(&event->WaitList, &self->SchedulerLink);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeBlockThread(self, &event->Header);
|
||||
}
|
||||
}
|
||||
// ke_event.c - synchronisation events
|
||||
#include <stdbool.h>
|
||||
#include <ke_event.h>
|
||||
#include <ke_thread.h>
|
||||
#include <ke_sched.h>
|
||||
#include <ke_irql.h>
|
||||
#include <ke_apc.h>
|
||||
#include <ob_object.h>
|
||||
|
||||
static void KiEventDestroy(OBJECT* obj) { (void)obj; }
|
||||
|
||||
__declspec(dllexport) 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 = KiEventDestroy;
|
||||
e->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
e->Type = type;
|
||||
e->Signaled = initialState ? 1 : 0;
|
||||
LIST_INIT(&e->WaitList);
|
||||
*out = e;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void KeSignalEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
|
||||
if (event->Type == EventManualReset) {
|
||||
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, flags);
|
||||
KeUnblockThreadWithStatus(t, STATUS_SUCCESS);
|
||||
flags = KeAcquireSpinlock(&event->Lock);
|
||||
}
|
||||
} else {
|
||||
if (!LIST_IS_EMPTY(&event->WaitList)) {
|
||||
// Auto-reset handoff: transfer the signal directly to exactly one
|
||||
// waiter. Do not leave Signaled=1, because a later waiter can steal
|
||||
// the disk/APC completion before the selected thread resumes.
|
||||
event->Signaled = 0;
|
||||
LIST_ENTRY* node = ListPopHead(&event->WaitList);
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
KeUnblockThreadWithStatus(t, STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
event->Signaled = 1;
|
||||
}
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void KeClearEvent(EVENT* event) {
|
||||
if (!event) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
}
|
||||
|
||||
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event, uint8_t alertable) {
|
||||
if (!event) return STATUS_INVALID_PARAMETER;
|
||||
if (!KeCanWait()) return STATUS_INVALID_IRQL;
|
||||
if (alertable && KeAreKernelApcsDisabled()) return STATUS_INVALID_PARAMETER;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&event->Lock);
|
||||
if (event->Signaled) {
|
||||
if (event->Type == EventAutoReset) event->Signaled = 0;
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KePrepareBlockThread(self, &event->Header, alertable);
|
||||
ListInsertTail(&event->WaitList, &self->SchedulerLink);
|
||||
KeSetThreadWaitList(self, &event->WaitList);
|
||||
KeReleaseSpinlock(&event->Lock, flags);
|
||||
return KeCommitBlockThread(self, alertable);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user