// XFESystem native services used by Microsoft minipal. There is no POSIX host.
#include "../NativePal.h"
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
extern "C" int* __errno_location();
extern "C" uint64_t xfe_runtime_mono_ns();
struct XfeTimespec { int64_t seconds,nanoseconds; };
static int failure(int code) { *__errno_location()=code; return -1; }
extern "C" int clock_gettime(int clock, XfeTimespec* value) {
    if (!value) return failure(14);
    uint64_t ns;
    if (clock==1 || clock==4 || clock==6) ns=xfe_runtime_mono_ns();
    else if (clock==0) {
        const XfeRuntimePal* p=XfeRuntimeGetPal();
        if (!p || !p->utc_filetime) return failure(38);
        uint64_t ticks=p->utc_filetime();
        if(ticks<116444736000000000ULL) return failure(38);
        uint64_t unix_ticks=ticks-116444736000000000ULL;
        value->seconds=(int64_t)(unix_ticks/10000000);
        value->nanoseconds=(int64_t)(unix_ticks%10000000)*100;return 0;
    } else return failure(22);
    value->seconds=(int64_t)(ns/1000000000);value->nanoseconds=(int64_t)(ns%1000000000);return 0;
}
extern "C" int nanosleep(const XfeTimespec* request,XfeTimespec* remaining) {
    if(!request) return failure(14);
    if(request->seconds<0 || request->nanoseconds<0 || request->nanoseconds>=1000000000) return failure(22);
    const XfeRuntimePal* p=XfeRuntimeGetPal();if(!p) return failure(38);
    if((uint64_t)request->seconds>(UINT64_MAX-(uint64_t)request->nanoseconds)/1000000000) return failure(22);
    uint64_t ns=(uint64_t)request->seconds*1000000000+(uint64_t)request->nanoseconds;
    uint64_t start=p->monotonic_nanoseconds();
    while(p->monotonic_nanoseconds()-start<ns) {
        uint64_t elapsed=p->monotonic_nanoseconds()-start;
        uint64_t left=elapsed<ns?ns-elapsed:0;
        if(left>=1000000)p->sleep_milliseconds(left/1000000>0xfffffffeULL?0xfffffffeU:(uint32_t)(left/1000000));
        else p->yield();
    }
    if(remaining)*remaining={0,0};return 0;
}
// The core executes one kernel process; Linux's gettid number is used by
// minipal only as a stable numeric identity. Other Linux syscalls are rejected.
extern "C" int64_t syscall(int64_t number,...) {
    if(number==186) { auto p=XfeRuntimeGetPal();return p?(int64_t)p->current_thread_id():failure(38); }
    return failure(38);
}
// Persistent storage and Linux /proc are unavailable in this RAM-only kernel.
extern "C" int open64(const char*,int,...) { return failure(2); }
extern "C" int64_t read(int,void*,size_t) { return failure(9); }
extern "C" int close(int) { return failure(9); }
