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:
maksw committed 2026-05-19 20:56:15 +02:00
1 parent f5fd7bdd75
commit 529f816166
75 files changed
+9969 -5675

No files matched your search

+71 -65
View File
@@ -1,65 +1,71 @@
// ke_semaphore.c - counting semaphore
#include <stdbool.h>
#include <ke_semaphore.h>
#include <ke_thread.h>
#include <ke_sched.h>
#include <ob_object.h>
static void SemDestroy(OBJECT* obj) { (void)obj; }
__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
if (!out || initial < 0 || max < 1 || initial > max)
return STATUS_INVALID_PARAMETER;
SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE));
if (!s) return STATUS_NO_MEMORY;
s->Header.Destroy = SemDestroy;
s->Lock = (SPINLOCK)SPINLOCK_INIT;
s->Count = initial;
s->MaxCount = max;
LIST_INIT(&s->WaitList);
*out = s;
return STATUS_SUCCESS;
}
__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
if (!sem) return STATUS_INVALID_PARAMETER;
THREAD* self = KeGetCurrentThread();
while (true) {
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (sem->Count > 0) {
sem->Count--;
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_SUCCESS;
}
ListInsertTail(&sem->WaitList, &self->SchedulerLink);
KeReleaseSpinlock(&sem->Lock, flags);
KeBlockThread(self, &sem->Header);
}
}
__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
if (!sem) return STATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (sem->Count > 0) {
sem->Count--;
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_SUCCESS;
}
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_FAILURE;
}
__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) {
if (!sem) return;
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (!LIST_IS_EMPTY(&sem->WaitList)) {
LIST_ENTRY* node = ListPopHead(&sem->WaitList);
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
KeReleaseSpinlock(&sem->Lock, flags);
KeUnblockThread(waiter);
return;
}
if (sem->Count < sem->MaxCount) sem->Count++;
KeReleaseSpinlock(&sem->Lock, flags);
}
// ke_semaphore.c - counting semaphore
#include <stdbool.h>
#include <ke_semaphore.h>
#include <ke_thread.h>
#include <ke_sched.h>
#include <ke_irql.h>
#include <ob_object.h>
static void KiSemaphoreDestroy(OBJECT* obj) { (void)obj; }
__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) {
if (!out || initial < 0 || max < 1 || initial > max)
return STATUS_INVALID_PARAMETER;
SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE));
if (!s) return STATUS_NO_MEMORY;
s->Header.Destroy = KiSemaphoreDestroy;
s->Lock = (SPINLOCK)SPINLOCK_INIT;
s->Count = initial;
s->MaxCount = max;
LIST_INIT(&s->WaitList);
*out = s;
return STATUS_SUCCESS;
}
__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) {
if (!sem) return STATUS_INVALID_PARAMETER;
if (!KeCanWait()) return STATUS_INVALID_IRQL;
THREAD* self = KeGetCurrentThread();
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (sem->Count > 0) {
sem->Count--;
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_SUCCESS;
}
KePrepareBlockThread(self, &sem->Header, 0);
ListInsertTail(&sem->WaitList, &self->SchedulerLink);
KeSetThreadWaitList(self, &sem->WaitList);
KeReleaseSpinlock(&sem->Lock, flags);
return KeCommitBlockThread(self, 0);
}
__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) {
if (!sem) return STATUS_INVALID_PARAMETER;
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (sem->Count > 0) {
sem->Count--;
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_SUCCESS;
}
KeReleaseSpinlock(&sem->Lock, flags);
return STATUS_FAILURE;
}
__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) {
if (!sem) return;
uintptr_t flags = KeAcquireSpinlock(&sem->Lock);
if (!LIST_IS_EMPTY(&sem->WaitList)) {
// Transfer this semaphore release directly to the selected waiter. The
// count stays unchanged; the waiter returns success without looping and
// consuming a count later.
LIST_ENTRY* node = ListPopHead(&sem->WaitList);
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
KeReleaseSpinlock(&sem->Lock, flags);
KeUnblockThreadWithStatus(waiter, STATUS_SUCCESS);
return;
}
if (sem->Count < sem->MaxCount) sem->Count++;
KeReleaseSpinlock(&sem->Lock, flags);
}