add ntfs.sys standalone driver target, change default usb vhd layout formatting to ntfs, implement Fat32CreateDir for directory creation support in the fat32 file system driver, add a dedicated HAL serial output endpoint for COM1 writes in hal_serial.c and subscribe serial to HAL text streams, introduce waitable kernel timers with KeTimerCreate, KeTimerSet, and KeTimerCancel alongside spinlock-protected global timer list initialization and scheduler tick tracking, implement SyscallWriteFileAsync system call for asynchronous non-blocking file writes, refactor NetSocketConnect and NetSocketSendTo to use generic SYS_SOCKET_ADDRESS_K structures instead of being hardcoded to IPv4, update gethostbyname and DNS name resolution to support IPv6 parsing via ResolveNameFamily, update tcpserve.exe with -4 and -6 command-line flags to accept and display IPv6 addresses, append size and version headers to all kernel telemetry and statistics structures including SYS_PMM_STATS, SYS_CPU_STATS, and SYS_SCHEDULER_STATS, update winmm timeGetTime to look up high-resolution hardware frequencies via SysGetTickFrequency, integrate 14 native smoke test applications.
This commit is contained in:
1 parent
2c4a68a75f
commit
ed3d065abd
156 files changed
+10509
-2643
No files matched your search
@@ -0,0 +1,219 @@
|
||||
// Kernel waitable timer objects. This file owns timer deadlines and timer wait signaling.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <kernel/ke_timer.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
#include <kernel/ob_object.h>
|
||||
|
||||
#define TIMER_SIGNAL_BATCH 32u
|
||||
|
||||
static LIST_ENTRY gTimerList;
|
||||
static SPINLOCK gTimerLock;
|
||||
static uint8_t gTimerInitialized;
|
||||
|
||||
// Initializes the global timer list on first use.
|
||||
static void KiTimerEnsureInitialized(void) {
|
||||
if (gTimerInitialized)
|
||||
return;
|
||||
|
||||
gTimerLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
LIST_INIT(&gTimerList);
|
||||
gTimerInitialized = 1;
|
||||
}
|
||||
|
||||
// Reads the scheduler tick value used by timer deadlines.
|
||||
static uint64_t KiTimerReadSchedulerTick(void) {
|
||||
KE_SCHED_STATS stats;
|
||||
KeGetSchedulerStats(&stats);
|
||||
return stats.Ticks;
|
||||
}
|
||||
|
||||
// Converts a millisecond interval to at least one scheduler tick.
|
||||
static uint64_t KiTimerMillisecondsToTicks(uint64_t milliseconds) {
|
||||
if (milliseconds == 0)
|
||||
return 0;
|
||||
|
||||
uint64_t ticks = milliseconds / SCHED_TICK_MS;
|
||||
if ((milliseconds % SCHED_TICK_MS) != 0)
|
||||
ticks++;
|
||||
return ticks ? ticks : 1;
|
||||
}
|
||||
|
||||
// Adds a tick interval to the current scheduler tick with saturation.
|
||||
static uint64_t KiTimerDeadlineFromNow(uint64_t intervalTicks) {
|
||||
uint64_t now = KiTimerReadSchedulerTick();
|
||||
uint64_t due = now + intervalTicks;
|
||||
return due < now ? UINT64_MAX : due;
|
||||
}
|
||||
|
||||
// Removes an active timer from the global deadline list while the timer lock is held.
|
||||
static uint8_t KiTimerRemoveLocked(KTIMER* timer) {
|
||||
if (!timer || !timer->Linked)
|
||||
return 0;
|
||||
|
||||
ListRemove(&timer->Link);
|
||||
timer->Linked = 0;
|
||||
timer->Active = 0;
|
||||
timer->DueTick = 0;
|
||||
timer->PeriodTicks = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Implements the timer Destroy operation.
|
||||
static void KiTimerDestroy(OBJECT* obj) {
|
||||
KTIMER* timer = (KTIMER*)obj;
|
||||
if (!timer)
|
||||
return;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
uintptr_t flags = KeAcquireSpinlock(&gTimerLock);
|
||||
(void)KiTimerRemoveLocked(timer);
|
||||
KeReleaseSpinlock(&gTimerLock, flags);
|
||||
|
||||
if (timer->Event) {
|
||||
ObDereferenceObject(&timer->Event->Header);
|
||||
timer->Event = (EVENT*)0;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an unset waitable timer object.
|
||||
KSTATUS KeTimerCreate(KTIMER** out) {
|
||||
if (!out)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
*out = (KTIMER*)0;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
KTIMER* timer = (KTIMER*)ObAllocateObject(ObjectTypeTimer, sizeof(KTIMER));
|
||||
if (!timer)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
timer->Header.Destroy = KiTimerDestroy;
|
||||
LIST_INIT(&timer->Link);
|
||||
|
||||
KSTATUS s = KeEventCreate(EventAutoReset, 0, &timer->Event);
|
||||
if (!KSUCCESS(s)) {
|
||||
ObDereferenceObject(&timer->Header);
|
||||
return s;
|
||||
}
|
||||
|
||||
*out = timer;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Arms or rearms a timer with a relative due time and optional period.
|
||||
KSTATUS KeTimerSet(KTIMER* timer, uint64_t dueTimeMilliseconds, uint64_t periodMilliseconds) {
|
||||
if (!timer || !timer->Event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
uint64_t dueTicks = KiTimerMillisecondsToTicks(dueTimeMilliseconds);
|
||||
uint64_t periodTicks = KiTimerMillisecondsToTicks(periodMilliseconds);
|
||||
uint8_t dropListReference = 0;
|
||||
uint8_t addListReference = 0;
|
||||
uint8_t signalNow = dueTicks == 0;
|
||||
EVENT* event = timer->Event;
|
||||
ObReferenceObject(&event->Header);
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gTimerLock);
|
||||
|
||||
if (timer->Linked) {
|
||||
if (signalNow && periodTicks == 0) {
|
||||
dropListReference = KiTimerRemoveLocked(timer);
|
||||
} else {
|
||||
timer->DueTick = KiTimerDeadlineFromNow(signalNow ? periodTicks : dueTicks);
|
||||
timer->PeriodTicks = periodTicks;
|
||||
timer->Active = 1;
|
||||
}
|
||||
} else if (!signalNow || periodTicks != 0) {
|
||||
timer->DueTick = KiTimerDeadlineFromNow(signalNow ? periodTicks : dueTicks);
|
||||
timer->PeriodTicks = periodTicks;
|
||||
timer->Active = 1;
|
||||
timer->Linked = 1;
|
||||
ListInsertTail(&gTimerList, &timer->Link);
|
||||
addListReference = 1;
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gTimerLock, flags);
|
||||
|
||||
if (addListReference)
|
||||
ObReferenceObject(&timer->Header);
|
||||
if (dropListReference)
|
||||
ObDereferenceObject(&timer->Header);
|
||||
|
||||
KeClearEvent(event);
|
||||
if (signalNow)
|
||||
KeSignalEvent(event);
|
||||
ObDereferenceObject(&event->Header);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Cancels a timer and clears any retained signal.
|
||||
KSTATUS KeTimerCancel(KTIMER* timer) {
|
||||
if (!timer || !timer->Event)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gTimerLock);
|
||||
uint8_t hadListReference = KiTimerRemoveLocked(timer);
|
||||
KeReleaseSpinlock(&gTimerLock, flags);
|
||||
|
||||
if (hadListReference)
|
||||
ObDereferenceObject(&timer->Header);
|
||||
KeClearEvent(timer->Event);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns the event that backs timer waits.
|
||||
EVENT* KeTimerWaitEvent(KTIMER* timer) {
|
||||
if (!timer)
|
||||
return (EVENT*)0;
|
||||
return timer->Event;
|
||||
}
|
||||
|
||||
// Services expired timers from the scheduler tick path.
|
||||
void KeTimerTick(void) {
|
||||
KiTimerEnsureInitialized();
|
||||
|
||||
EVENT* events[TIMER_SIGNAL_BATCH];
|
||||
KTIMER* listReferencesToDrop[TIMER_SIGNAL_BATCH];
|
||||
uint32_t count = 0;
|
||||
uint32_t dropCount = 0;
|
||||
uint64_t now = KiTimerReadSchedulerTick();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gTimerLock);
|
||||
LIST_ENTRY* node = gTimerList.Fwd;
|
||||
while (node != &gTimerList && count < TIMER_SIGNAL_BATCH) {
|
||||
LIST_ENTRY* next = node->Fwd;
|
||||
KTIMER* timer = CONTAINING_RECORD(node, KTIMER, Link);
|
||||
|
||||
if (timer->Active && timer->DueTick <= now) {
|
||||
if (timer->Event) {
|
||||
ObReferenceObject(&timer->Event->Header);
|
||||
events[count++] = timer->Event;
|
||||
}
|
||||
|
||||
if (timer->PeriodTicks != 0) {
|
||||
uint64_t due = now + timer->PeriodTicks;
|
||||
timer->DueTick = due < now ? UINT64_MAX : due;
|
||||
} else {
|
||||
if (KiTimerRemoveLocked(timer))
|
||||
listReferencesToDrop[dropCount++] = timer;
|
||||
}
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
KeReleaseSpinlock(&gTimerLock, flags);
|
||||
|
||||
for (uint32_t i = 0; i < dropCount; i++)
|
||||
ObDereferenceObject(&listReferencesToDrop[i]->Header);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
KeSignalEvent(events[i]);
|
||||
ObDereferenceObject(&events[i]->Header);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user