namespace XFESystem.NativeKernel; // Generation-tagged handles prevent a closed handle from targeting a reused slot. // Waiters are real parked kernel threads; manual and auto reset have separate state. public static unsafe class KernelEvents { const uint Capacity = 128; public const uint Timeout = 258, Failure = 0xffffffff; static ulong* _events; static ulong _generation; public static bool Initialize() { _events = (ulong*)Native.Storage(9); return _events != null; } static int Slot(ulong handle) { uint number = (uint)(handle & 255); if (_events == null || number == 0 || number > Capacity) return -1; uint slot = number - 1; return _events[slot * 4] == handle ? (int)slot : -1; } public static ulong Create(bool manual, bool initial) { ulong flags = Native.IrqSave(), result = 0; if (_events != null) for (uint i = 0; i < Capacity; i++) if (_events[i * 4] == 0) { result = (++_generation << 8) | (i + 1); _events[i * 4] = result; _events[i * 4 + 1] = manual ? 1UL : 0UL; _events[i * 4 + 2] = initial ? 1UL : 0UL; break; } Native.IrqRestore(flags); return result; } public static bool Close(ulong handle) { ulong flags = Native.IrqSave(); int slot = Slot(handle); if (slot >= 0) { _events[slot * 4] = 0; Threads.WakeEvent(handle); } Native.IrqRestore(flags); return slot >= 0; } public static bool Set(ulong handle) { ulong flags = Native.IrqSave(); int slot = Slot(handle); if (slot >= 0) { _events[slot * 4 + 2] = 1; Threads.WakeEvent(handle); } Native.IrqRestore(flags); return slot >= 0; } public static bool Reset(ulong handle) { ulong flags = Native.IrqSave(); int slot = Slot(handle); if (slot >= 0) _events[slot * 4 + 2] = 0; Native.IrqRestore(flags); return slot >= 0; } public static uint Wait(ulong* handles, uint count, uint milliseconds) { if (handles == null || count == 0 || count > 64 || !Threads.Ready) return Failure; ulong deadline = milliseconds == 0xffffffff ? ~0UL : MonotonicClock.Nanoseconds() + (ulong)milliseconds * 1000000; for (;;) { ulong flags = Native.IrqSave(); for (uint i = 0; i < count; i++) { int slot = Slot(handles[i]); if (slot < 0) { Native.IrqRestore(flags); return Failure; } if (_events[slot * 4 + 2] != 0) { if (_events[slot * 4 + 1] == 0) _events[slot * 4 + 2] = 0; Native.IrqRestore(flags); return i; } } if (MonotonicClock.Nanoseconds() >= deadline) { Native.IrqRestore(flags); return Timeout; } Threads.ParkEvent(count == 1 ? handles[0] : ~0UL, deadline); Native.IrqRestore(flags); } } }