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);
}
}
}
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);
}
}
}