XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Runtime.InteropServices;
namespace XFESystem.NativeKernel;

[StructLayout(LayoutKind.Sequential)]
public struct ThreadProbe { public ulong Tls, Canary, Steps, Errors, PeerSteps, Done, Deadline, TickAddress, StartTicks; }
public static unsafe class ThreadSelfTest
{
    static ulong _event;
    static ulong _eventStep;
    [UnmanagedCallersOnly(EntryPoint = "xfe_kernel_event_probe")]
    public static uint EventProbe(void* argument)
    {
        Threads.Sleep(20);
        _eventStep = 1;
        if (!KernelEvents.Set(_event)) return 0;
        return 1;
    }
    public static bool Run()
    {
        if (!Threads.Ready || !KernelEvents.Initialize() || !LocalApicTimer.Initialize()) return false;
        ulong page = PhysicalMemory.Allocate();
        if (page == 0) return false;
        byte* storage = (byte*)PhysicalMemory.ToVirtual(page);
        ThreadProbe* a = (ThreadProbe*)storage;
        ThreadProbe* b = (ThreadProbe*)(storage + 128);
        ulong* tlsA = (ulong*)(storage + 256), tlsB = (ulong*)(storage + 384);
        *tlsA = 0x5846455448524431; *tlsB = 0x5846455448524432;
        a->Tls = (ulong)tlsA; b->Tls = (ulong)tlsB;
        a->Canary = *tlsA; b->Canary = *tlsB;
        a->PeerSteps = (ulong)&b->Steps; b->PeerSteps = (ulong)&a->Steps;
        a->TickAddress = b->TickAddress = (ulong)Native.Storage(14);
        a->StartTicks = b->StartTicks = LocalApicTimer.Ticks;
        a->Deadline = b->Deadline = Native.ReadTsc() + MonotonicClock.Frequency * 3;
        ulong oldPreemptions = Threads.Preemptions;
        delegate* unmanaged<void*, uint> probe = (delegate* unmanaged<void*, uint>)Native.ThreadProbeAddress();
        if (Threads.Create(probe, a, 65536, a->Tls, false) == 0 || Threads.Create(probe, b, 65536, b->Tls, false) == 0) return false;
        ulong timeout = MonotonicClock.Nanoseconds() + 4000000000;
        while ((a->Done == 0 || b->Done == 0) && MonotonicClock.Nanoseconds() < timeout) Threads.Yield();
        bool result = a->Done != 0 && b->Done != 0 && a->Errors == 0 && b->Errors == 0 &&
            a->Steps >= 100000 && b->Steps >= 100000 && Threads.Preemptions >= oldPreemptions + 3 && Native.ReadMsr(0xc0000100) == 0;
        Threads.Yield(); // reap finished guarded stacks only from another stack
        if (!PhysicalMemory.Release(page)) return false;
        _event = KernelEvents.Create(false, false);
        if (_event == 0 || Threads.Create(&EventProbe, null, 65536, 0, false) == 0) return false;
        ulong eventHandle = _event;
        uint wait = KernelEvents.Wait(&eventHandle, 1, 1000);
        if (wait != 0 || _eventStep != 1 || KernelEvents.Wait(&eventHandle, 1, 0) != KernelEvents.Timeout) return false;
        if (!KernelEvents.Close(_event) || KernelEvents.Set(_event)) return false;
        ulong manual = KernelEvents.Create(true, true);
        if (manual == 0 || KernelEvents.Wait(&manual, 1, 0) != 0 || KernelEvents.Wait(&manual, 1, 0) != 0 ||
            !KernelEvents.Reset(manual) || KernelEvents.Wait(&manual, 1, 2) != KernelEvents.Timeout || !KernelEvents.Close(manual)) return false;
        Threads.Yield();
        return result;
    }
}