/*
 * Copyright (c) 2026, Chloe M.
 * Provided under the BSD-3 clause.
 *
 * Description: Thread management
 * Author:      Chloe M.
 */

#include <ps/thread.h>
#include <ps/process.h>
#include <hal/thread.h>
#include <hal/prim.h>
#include <hal/kpcr.h>
#include <ke/bugcheck.h>
#include <ex/pool.h>
#include <atomic.h>

/* Globals */
static UQUAD NextThreadTid = 0;
static SCHED_QUEUE ReaperQueue;

PT_STATUS
PsCreateThread(struct _PROCESS *Parent, ULONG Flags, UPTR Ip, THREAD **Result)
{
    THREAD *Thread;
    PT_STATUS Status;

    if (Parent == NULL || Result == NULL) {
        return STATUS_INVALID_PARAM;
    }

    Thread = ExAllocatePoolWithTag(
        POOL_NON_PAGED,
        sizeof(*Thread),
        THREAD_POOL_TAG
    );

    if (Thread == NULL) {
        return STATUS_NO_MEMORY;
    }

    Thread->Tid = AtomicIncQuad(&NextThreadTid);
    Thread->Parent = Parent;
    Status = HalThreadInit(Thread, Flags, Ip);
    if (PT_ERROR(Status)) {
        ExFreePoolWithTag(Thread, THREAD_POOL_TAG);
        return Status;
    }

    *Result = Thread;
    return STATUS_SUCCESS;
}

NO_RETURN VOID
PsExitThread(ULONG ExitCode)
{
    KPCR *Kpcr;
    THREAD *CurrentThread;
    PROCESS *CurrentProcess;

    Kpcr = HalKpcrCurrent();
    CurrentThread = Kpcr->CurrentThread;
    CurrentProcess = CurrentThread->Parent;

    /* Cannot kill the root thread */
    if (CurrentThread->Tid == 1 && CurrentProcess->Pid == 1) {
        KeBugCheck(
            BUGCHECK_SYSTEMPROC_KILLED,
            "crts.sys terminated\n"
        );
    }

    KeSchedEnqueue(&ReaperQueue, CurrentThread);
    Kpcr->CurrentThread = NULL;
    HalThreadYield();

    for (;;) {
        HalCpuSuspend();
    }
}

VOID
PsThreadInit(VOID)
{
    SCHED_QUEUE_INIT(&ReaperQueue);
}
