exectos/xtoskrnl/ke/kthread.c
Rafal Kupiec 331c5bfeda
All checks were successful
Builds / ExectOS (i686) (push) Successful in 34s
Builds / ExectOS (amd64) (push) Successful in 36s
Rework initial timer support
2024-04-20 23:15:57 +02:00

291 lines
7.7 KiB
C

/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/kthread.c
* DESCRIPTION: XT kernel thread manipulation support
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtos.h>
/**
* Initializes the thread.
*
* @param Process
* Supplies a pointer to the process that owns the thread.
*
* @param Thread
* Supplies a pointer to thread that will be initialized.
*
* @param SystemRoutine
* Supplies a pointer to the routine called during first scheduling.
*
* @param StartRoutine
* Supplies a pointer to the routine called during thread startup.
*
* @param StartContext
* Supplies a pointer to a context data that will be passed to start routine.
*
* @param Context
* Supplies a pointer to the context frame containing state of the user mode thread.
*
* @param EnvironmentBlock
* Supplies a pointer to the environment block of the thread.
*
* @param Stack
* Supplies a pointer to the stack of the thread.
*
* @return This routine returns a status code.
*
* @since NT 3.5
*/
XTAPI
XTSTATUS
KeInitializeThread(IN PKPROCESS Process,
IN OUT PKTHREAD Thread,
IN PKSYSTEM_ROUTINE SystemRoutine,
IN PKSTART_ROUTINE StartRoutine,
IN PVOID StartContext,
IN PCONTEXT Context,
IN PVOID EnvironmentBlock,
IN PVOID Stack,
IN BOOLEAN StartThread)
{
PKWAIT_BLOCK TimerWaitBlock;
BOOLEAN Allocation;
XTSTATUS Status;
ULONG Index;
/* No stack allocation was done yet */
Allocation = FALSE;
/* Initialize thread dispatcher header */
Thread->Header.Type = ThreadObject;
Thread->Header.SignalState = 0;
/* Initialize thread wait list */
RtlInitializeListHead(&Thread->Header.WaitListHead);
/* Initialize thread mutant list head */
RtlInitializeListHead(&Thread->MutantListHead);
/* Initialize the builtin wait blocks */
for(Index = 0; Index <= KTHREAD_WAIT_BLOCK; Index++)
{
Thread->WaitBlock[Index].Thread = Thread;
}
/* Initialize stack resident and stack swap */
Thread->AutoAlignment = Process->AutoAlignment;
Thread->StackResident = TRUE;
Thread->StackSwap = TRUE;
Thread->SwapBusy = FALSE;
/* Set priority adjustment reason */
Thread->AdjustReason = AdjustNone;
/* Initialize thread lock */
KeInitializeSpinLock(&Thread->ThreadLock);
/* Set thread service table */
Thread->ServiceTable = KeServiceDescriptorTable;
/* Initialize thread APC */
Thread->ApcStatePointer[0] = &Thread->ApcState;
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
Thread->ApcQueueable = TRUE;
Thread->ApcState.Process = Process;
Thread->Process = Process;
/* Initialize APC list heads */
RtlInitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
RtlInitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
/* Initialize APC queue lock */
KeInitializeSpinLock(&Thread->ApcQueueLock);
/* Initialize kernel-mode suspend APC */
KeInitializeApc(&Thread->SuspendApc, Thread, OriginalApcEnvironment, KepSuspendNop,
KepSuspendRundown, KepSuspendThread, KernelMode, NULL);
/* Initialize suspend semaphore */
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);
/* Initialize the builtin timer */
KeInitializeTimer(&Thread->Timer, NotificationTimer);
TimerWaitBlock = &Thread->WaitBlock[KTIMER_WAIT_BLOCK];
TimerWaitBlock->Object = &Thread->Timer;
TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
TimerWaitBlock->WaitType = WaitAny;
TimerWaitBlock->WaitListEntry.Flink = &(&Thread->Timer)->Header.WaitListHead;
TimerWaitBlock->WaitListEntry.Blink = &(&Thread->Timer)->Header.WaitListHead;
/* Initialize Thread Environment Block*/
Thread->EnvironmentBlock = EnvironmentBlock;
/* Make sure there is a valid stack available */
if(!Stack)
{
/* Allocate new stack */
Status = MmAllocateKernelStack(&Stack, FALSE, 0);
if(Status != STATUS_SUCCESS || !Stack)
{
/* Stack allocation failed */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Mark allocation as successful */
Allocation = TRUE;
}
Thread->InitialStack = Stack;
Thread->StackBase = Stack;
Thread->StackLimit = Stack - KERNEL_STACK_SIZE;
__try
{
/* Initialize thread context */
KepInitializeThreadContext(Thread, SystemRoutine, StartRoutine, StartContext, Context);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
/* Failed to initialize thread context, check stack allocation */
if(Allocation)
{
/* Deallocate stack */
MmFreeKernelStack(Stack, FALSE);
Thread->InitialStack = NULL;
Thread->StackBase = NULL;
}
/* Thread initialization failed */
return STATUS_UNSUCCESSFUL;
}
/* Mark thread as initialized and run it */
Thread->State = Initialized;
/* Check if thread should be started */
if(StartThread)
{
/* Start thread */
KeStartThread(Thread);
}
/* Return success */
return STATUS_SUCCESS;
}
/**
* Starts the thread.
*
* @param Thread
* Supplies a pointer to the thread.
*
* @return This routine does not return any value.
*
* @since NT 5.1
*/
XTAPI
VOID
KeStartThread(IN PKTHREAD Thread)
{
UNIMPLEMENTED;
}
/**
* Exits the dispatcher, switches context to a new thread and lowers runlevel to its original state.
*
* @param OldRunLevel
* Supplies the original runlevel state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KepExitDispatcher(IN KRUNLEVEL OldRunLevel)
{
UNIMPLEMENTED;
/* Lower runlevel */
KeLowerRunLevel(OldRunLevel);
}
/**
* Suspend APC-built thread NOP routine. It takes no actions.
*
* @param Apc
* Supplies a pointer to the APC object.
*
* @param NormalRoutine
* Supplies a pointer to the normal routine set during the APC initialization. Unused by this routine.
*
* @param NormalContext
* Supplies a pointer a context data set during the APC initialization. Unused by this routine.
*
* @param SystemArgument1
* Supplies a pointer to an unused system argument.
*
* @param SystemArgument2
* Supplies a pointer to an unused system argument.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KepSuspendNop(IN PKAPC Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2)
{
/* No action here */
}
/**
* Suspend APC-built thread rundown routine. It takes no actions.
*
* @param Apc
* Supplies a pointer to the APC object.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KepSuspendRundown(IN PKAPC Apc)
{
/* No action here */
}
/**
* Suspends thread execution by waiting on the thread's semaphore.
*
* @param NormalContext
* Supplies a pointer a context data set during the APC initialization. Unused by this routine.
*
* @param SystemArgument1
* Supplies a pointer to an unused system argument.
*
* @param SystemArgument2
* Supplies a pointer to an unused system argument.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KepSuspendThread(IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
UNIMPLEMENTED;
}