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

+73 -66
View File
@@ -1,66 +1,73 @@
// ke_mutex.c - binary ownership mutex
#include <stdbool.h>
#include <ke_mutex.h>
#include <ke_thread.h>
#include <ke_sched.h>
#include <mm_virt.h>
#include <ob_object.h>
static void MutexDestroy(OBJECT* obj) { (void)obj; }
KSTATUS MutexCreate(MUTEX **out) {
if (!out) return STATUS_INVALID_PARAMETER;
MUTEX* m = (MUTEX *)ObAllocateObject(ObjectTypeMutex, sizeof(MUTEX));
if (!m) return STATUS_NO_MEMORY;
m->Header.Destroy = MutexDestroy;
m->Lock = (SPINLOCK)SPINLOCK_INIT;
m->Owner = (struct THREAD *)0;
LIST_INIT(&m->WaitList);
*out = m;
return STATUS_SUCCESS;
}
KSTATUS KeAcquireMutex(MUTEX* mutex) {
if (!mutex) return STATUS_INVALID_PARAMETER;
THREAD* self = KeGetCurrentThread();
while (true) {
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
if (!mutex->Owner) {
mutex->Owner = self;
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_SUCCESS;
}
ListInsertTail(&mutex->WaitList, &self->SchedulerLink);
KeReleaseSpinlock(&mutex->Lock, flags);
KeBlockThread(self, &mutex->Header);
}
}
KSTATUS KeTryAcquireMutex(MUTEX* mutex) {
if (!mutex) return STATUS_INVALID_PARAMETER;
THREAD* self = KeGetCurrentThread();
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
if (!mutex->Owner) {
mutex->Owner = self;
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_SUCCESS;
}
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_FAILURE;
}
void KeReleaseMutex(MUTEX* mutex) {
if (!mutex) return;
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
mutex->Owner = (struct THREAD *)0;
if (!LIST_IS_EMPTY(&mutex->WaitList)) {
LIST_ENTRY* node = ListPopHead(&mutex->WaitList);
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
KeReleaseSpinlock(&mutex->Lock, flags);
KeUnblockThread(waiter);
return;
}
KeReleaseSpinlock(&mutex->Lock, flags);
}
// ke_mutex.c - binary ownership mutex
#include <stdbool.h>
#include <ke_mutex.h>
#include <ke_thread.h>
#include <ke_sched.h>
#include <ke_irql.h>
#include <mm_virt.h>
#include <ob_object.h>
static void KiMutexDestroy(OBJECT* obj) { (void)obj; }
KSTATUS KeMutexCreate(MUTEX **out) {
if (!out) return STATUS_INVALID_PARAMETER;
MUTEX* m = (MUTEX *)ObAllocateObject(ObjectTypeMutex, sizeof(MUTEX));
if (!m) return STATUS_NO_MEMORY;
m->Header.Destroy = KiMutexDestroy;
m->Lock = (SPINLOCK)SPINLOCK_INIT;
m->Owner = (struct THREAD *)0;
LIST_INIT(&m->WaitList);
*out = m;
return STATUS_SUCCESS;
}
KSTATUS KeAcquireMutex(MUTEX* mutex) {
if (!mutex) return STATUS_INVALID_PARAMETER;
if (!KeCanWait()) return STATUS_INVALID_IRQL;
THREAD* self = KeGetCurrentThread();
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
if (!mutex->Owner) {
mutex->Owner = self;
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_SUCCESS;
}
KePrepareBlockThread(self, &mutex->Header, 0);
ListInsertTail(&mutex->WaitList, &self->SchedulerLink);
KeSetThreadWaitList(self, &mutex->WaitList);
KeReleaseSpinlock(&mutex->Lock, flags);
return KeCommitBlockThread(self, 0);
}
KSTATUS KeTryAcquireMutex(MUTEX* mutex) {
if (!mutex) return STATUS_INVALID_PARAMETER;
THREAD* self = KeGetCurrentThread();
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
if (!mutex->Owner) {
mutex->Owner = self;
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_SUCCESS;
}
KeReleaseSpinlock(&mutex->Lock, flags);
return STATUS_FAILURE;
}
void KeReleaseMutex(MUTEX* mutex) {
if (!mutex) return;
uintptr_t flags = KeAcquireSpinlock(&mutex->Lock);
if (!LIST_IS_EMPTY(&mutex->WaitList)) {
LIST_ENTRY* node = ListPopHead(&mutex->WaitList);
THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink);
// Direct handoff: the selected waiter owns the mutex when its wait
// returns. Do not drop Owner to NULL, or another thread can steal it.
mutex->Owner = waiter;
KeReleaseSpinlock(&mutex->Lock, flags);
KeUnblockThreadWithStatus(waiter, STATUS_SUCCESS);
return;
}
mutex->Owner = (struct THREAD *)0;
KeReleaseSpinlock(&mutex->Lock, flags);
}