mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-11 07:19:20 +00:00
Update kernel
This commit is contained in:
420
include/task.hpp
420
include/task.hpp
@ -32,14 +32,15 @@
|
||||
|
||||
namespace Tasking
|
||||
{
|
||||
/** @brief Instruction Pointer */
|
||||
using VirtualFileSystem::FileDescriptorTable;
|
||||
using VirtualFileSystem::Node;
|
||||
|
||||
/** Instruction Pointer */
|
||||
typedef __UINTPTR_TYPE__ IP;
|
||||
/** @brief Process ID */
|
||||
/** Process ID */
|
||||
typedef int PID;
|
||||
/** @brief Thread ID */
|
||||
/** Thread ID */
|
||||
typedef int TID;
|
||||
/* @brief Token */
|
||||
typedef __UINTPTR_TYPE__ Token;
|
||||
|
||||
enum TaskArchitecture
|
||||
{
|
||||
@ -47,7 +48,10 @@ namespace Tasking
|
||||
x32,
|
||||
x64,
|
||||
ARM32,
|
||||
ARM64
|
||||
ARM64,
|
||||
|
||||
_ArchitectureMin = UnknownArchitecture,
|
||||
_ArchitectureMax = ARM64
|
||||
};
|
||||
|
||||
enum TaskCompatibility
|
||||
@ -55,26 +59,35 @@ namespace Tasking
|
||||
UnknownPlatform,
|
||||
Native,
|
||||
Linux,
|
||||
Windows
|
||||
Windows,
|
||||
|
||||
_CompatibilityMin = UnknownPlatform,
|
||||
_CompatibilityMax = Windows
|
||||
};
|
||||
|
||||
enum TaskTrustLevel
|
||||
enum TaskExecutionMode
|
||||
{
|
||||
UnknownElevation,
|
||||
UnknownExecutionMode,
|
||||
Kernel,
|
||||
System,
|
||||
User
|
||||
User,
|
||||
|
||||
_ExecuteModeMin = UnknownExecutionMode,
|
||||
_ExecuteModeMax = User
|
||||
};
|
||||
|
||||
enum TaskStatus
|
||||
enum TaskStatus : int
|
||||
{
|
||||
UnknownStatus,
|
||||
Ready,
|
||||
Running,
|
||||
Sleeping,
|
||||
Waiting,
|
||||
Stopped,
|
||||
Terminated
|
||||
Blocked,
|
||||
Zombie,
|
||||
Terminated,
|
||||
|
||||
_StatusMin = UnknownStatus,
|
||||
_StatusMax = Terminated
|
||||
};
|
||||
|
||||
enum TaskPriority
|
||||
@ -84,60 +97,81 @@ namespace Tasking
|
||||
Low = 2,
|
||||
Normal = 5,
|
||||
High = 8,
|
||||
Critical = 10
|
||||
Critical = 10,
|
||||
|
||||
_PriorityMin = UnknownPriority,
|
||||
_PriorityMax = Critical
|
||||
};
|
||||
|
||||
enum KillErrorCodes : int
|
||||
{
|
||||
KILL_SCHEDULER_DESTRUCTION = -0xFFFF,
|
||||
KILL_CXXABI_EXCEPTION = -0xECE97,
|
||||
KILL_BY_OTHER_PROCESS = -0x7A55,
|
||||
KILL_SYSCALL = -0xCA11,
|
||||
KILL_CRASH = -0xDEAD,
|
||||
KILL_OOM = -0x1008,
|
||||
KILL_ERROR = -0x1,
|
||||
KILL_SUCCESS = 0,
|
||||
};
|
||||
|
||||
struct TaskSecurity
|
||||
{
|
||||
TaskTrustLevel TrustLevel;
|
||||
Token UniqueToken;
|
||||
bool IsCritical;
|
||||
bool IsDebugEnabled;
|
||||
bool IsKernelDebugEnabled;
|
||||
};
|
||||
|
||||
struct TaskInfo
|
||||
{
|
||||
size_t OldUserTime = 0;
|
||||
size_t OldKernelTime = 0;
|
||||
uint64_t OldUserTime = 0;
|
||||
uint64_t OldKernelTime = 0;
|
||||
|
||||
size_t SleepUntil = 0;
|
||||
size_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
||||
uint64_t Year, Month, Day, Hour, Minute, Second;
|
||||
bool Affinity[256]; // MAX_CPU
|
||||
TaskPriority Priority;
|
||||
TaskArchitecture Architecture;
|
||||
TaskCompatibility Compatibility;
|
||||
uint64_t SleepUntil = 0;
|
||||
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
|
||||
uint64_t Year = 0, Month = 0, Day = 0, Hour = 0, Minute = 0, Second = 0;
|
||||
bool Affinity[256] = {true}; // MAX_CPU
|
||||
TaskPriority Priority = TaskPriority::Normal;
|
||||
TaskArchitecture Architecture = TaskArchitecture::UnknownArchitecture;
|
||||
TaskCompatibility Compatibility = TaskCompatibility::UnknownPlatform;
|
||||
};
|
||||
|
||||
struct TCB
|
||||
/**
|
||||
* TCB struct for gs register
|
||||
*/
|
||||
struct gsTCB
|
||||
{
|
||||
/** @brief Used by syscall handler */
|
||||
uintptr_t SyscallStack; /* gs+0x0 */
|
||||
/**
|
||||
* Used by syscall handler
|
||||
*
|
||||
* gs+0x0
|
||||
*/
|
||||
uintptr_t SyscallStack = __UINTPTR_MAX__;
|
||||
|
||||
/** @brief Used by syscall handler */
|
||||
uintptr_t TempStack; /* gs+0x8 */
|
||||
/**
|
||||
* Used by syscall handler
|
||||
*
|
||||
* gs+0x8
|
||||
*/
|
||||
uintptr_t TempStack = __UINTPTR_MAX__;
|
||||
|
||||
TID ID;
|
||||
char Name[256];
|
||||
struct PCB *Parent;
|
||||
IP EntryPoint;
|
||||
int ExitCode;
|
||||
/**
|
||||
* The current thread class
|
||||
*/
|
||||
class TCB *t;
|
||||
};
|
||||
|
||||
class TCB
|
||||
{
|
||||
private:
|
||||
class Task *ctx = nullptr;
|
||||
|
||||
public:
|
||||
TID ID = -1;
|
||||
const char * Name = nullptr;
|
||||
class PCB *Parent = nullptr;
|
||||
IP EntryPoint = 0;
|
||||
|
||||
std::atomic_int ExitCode;
|
||||
std::atomic<TaskStatus> Status = TaskStatus::UnknownStatus;
|
||||
Memory::StackGuard *Stack;
|
||||
Memory::MemMgr *Memory;
|
||||
TaskStatus Status;
|
||||
int ErrorNumber;
|
||||
#if defined(a64)
|
||||
CPU::x64::TrapFrame Registers;
|
||||
CPU::x64::TrapFrame Registers{};
|
||||
uintptr_t ShadowGSBase, GSBase, FSBase;
|
||||
#elif defined(a32)
|
||||
CPU::x32::TrapFrame Registers; // TODO
|
||||
@ -146,52 +180,25 @@ namespace Tasking
|
||||
uintptr_t Registers; // TODO
|
||||
#endif
|
||||
uintptr_t IPHistory[128];
|
||||
TaskSecurity Security;
|
||||
TaskInfo Info;
|
||||
struct
|
||||
{
|
||||
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
|
||||
bool IsCritical = false;
|
||||
bool IsDebugEnabled = false;
|
||||
bool IsKernelDebugEnabled = false;
|
||||
} Security{};
|
||||
TaskInfo Info{};
|
||||
CPU::x64::FXState *FPU;
|
||||
|
||||
void Rename(const char *name)
|
||||
{
|
||||
CriticalSection cs;
|
||||
if (strlen(name) > 256 || strlen(name) == 0)
|
||||
{
|
||||
debug("Invalid thread name");
|
||||
return;
|
||||
}
|
||||
void Rename(const char *name);
|
||||
void SetPriority(TaskPriority priority);
|
||||
int GetExitCode() { return ExitCode.load(); }
|
||||
void SetCritical(bool Critical);
|
||||
void SetDebugMode(bool Enable);
|
||||
void SetKernelDebugMode(bool Enable);
|
||||
|
||||
trace("Renaming thread %s to %s", Name, name);
|
||||
strncpy(Name, name, 256);
|
||||
}
|
||||
|
||||
void SetPriority(TaskPriority priority)
|
||||
{
|
||||
CriticalSection cs;
|
||||
trace("Setting priority of thread %s to %d", Name, priority);
|
||||
Info.Priority = priority;
|
||||
}
|
||||
|
||||
int GetExitCode() { return ExitCode; }
|
||||
|
||||
void SetCritical(bool Critical)
|
||||
{
|
||||
CriticalSection cs;
|
||||
trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false");
|
||||
Security.IsCritical = Critical;
|
||||
}
|
||||
|
||||
void SetDebugMode(bool Enable)
|
||||
{
|
||||
CriticalSection cs;
|
||||
trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
||||
Security.IsDebugEnabled = Enable;
|
||||
}
|
||||
|
||||
void SetKernelDebugMode(bool Enable)
|
||||
{
|
||||
CriticalSection cs;
|
||||
trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false");
|
||||
Security.IsKernelDebugEnabled = Enable;
|
||||
}
|
||||
void Block() { Status.store(TaskStatus::Blocked); }
|
||||
void Unblock() { Status.store(TaskStatus::Ready); }
|
||||
|
||||
void SYSV_ABI_Call(uintptr_t Arg1 = 0,
|
||||
uintptr_t Arg2 = 0,
|
||||
@ -199,92 +206,79 @@ namespace Tasking
|
||||
uintptr_t Arg4 = 0,
|
||||
uintptr_t Arg5 = 0,
|
||||
uintptr_t Arg6 = 0,
|
||||
void *Function = nullptr)
|
||||
{
|
||||
CriticalSection cs;
|
||||
#if defined(a64)
|
||||
this->Registers.rdi = Arg1;
|
||||
this->Registers.rsi = Arg2;
|
||||
this->Registers.rdx = Arg3;
|
||||
this->Registers.rcx = Arg4;
|
||||
this->Registers.r8 = Arg5;
|
||||
this->Registers.r9 = Arg6;
|
||||
if (Function != nullptr)
|
||||
this->Registers.rip = (uint64_t)Function;
|
||||
#else
|
||||
#warning "SYSV ABI not implemented for this architecture"
|
||||
#endif
|
||||
}
|
||||
void *Function = nullptr);
|
||||
|
||||
TCB(class Task *ctx,
|
||||
PCB *Parent,
|
||||
IP EntryPoint,
|
||||
const char **argv = nullptr,
|
||||
const char **envp = nullptr,
|
||||
const std::vector<AuxiliaryVector> &auxv = std::vector<AuxiliaryVector>(),
|
||||
TaskArchitecture Architecture = TaskArchitecture::x64,
|
||||
TaskCompatibility Compatibility = TaskCompatibility::Native,
|
||||
bool ThreadNotReady = false);
|
||||
|
||||
~TCB();
|
||||
};
|
||||
|
||||
struct PCB
|
||||
class PCB
|
||||
{
|
||||
PID ID;
|
||||
char Name[256];
|
||||
PCB *Parent;
|
||||
int ExitCode;
|
||||
TaskStatus Status;
|
||||
TaskSecurity Security;
|
||||
TaskInfo Info;
|
||||
private:
|
||||
class Task *ctx = nullptr;
|
||||
bool OwnPageTable = false;
|
||||
|
||||
public:
|
||||
PID ID = -1;
|
||||
const char * Name = nullptr;
|
||||
PCB *Parent = nullptr;
|
||||
std::atomic_int ExitCode;
|
||||
std::atomic<TaskStatus> Status = Zombie;
|
||||
struct
|
||||
{
|
||||
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
|
||||
bool IsCritical = false;
|
||||
bool IsDebugEnabled = false;
|
||||
bool IsKernelDebugEnabled = false;
|
||||
struct
|
||||
{
|
||||
uint16_t UserID = UINT16_MAX;
|
||||
uint16_t GroupID = UINT16_MAX;
|
||||
} Real, Effective;
|
||||
} Security{};
|
||||
TaskInfo Info{};
|
||||
std::vector<TCB *> Threads;
|
||||
std::vector<PCB *> Children;
|
||||
InterProcessCommunication::IPC *IPC;
|
||||
Memory::PageTable *PageTable;
|
||||
SymbolResolver::Symbols *ELFSymbolTable;
|
||||
VirtualFileSystem::Node *CurrentWorkingDirectory;
|
||||
VirtualFileSystem::Node *ProcessDirectory;
|
||||
VirtualFileSystem::Node *memDirectory;
|
||||
|
||||
void SetWorkingDirectory(VirtualFileSystem::Node *node)
|
||||
{
|
||||
CriticalSection cs;
|
||||
trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name);
|
||||
CurrentWorkingDirectory = node;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Token Trust Level */
|
||||
enum TTL
|
||||
{
|
||||
UnknownTrustLevel = 0b0001,
|
||||
Untrusted = 0b0010,
|
||||
Trusted = 0b0100,
|
||||
TrustedByKernel = 0b1000,
|
||||
FullTrust = Trusted | TrustedByKernel,
|
||||
AllFlags = 0b1111
|
||||
};
|
||||
|
||||
class Security
|
||||
{
|
||||
private:
|
||||
struct TokenData
|
||||
{
|
||||
Token token;
|
||||
int TrustLevel;
|
||||
uint64_t OwnerID;
|
||||
bool Process;
|
||||
};
|
||||
|
||||
std::vector<TokenData> Tokens;
|
||||
Node *CurrentWorkingDirectory;
|
||||
Node *ProcessDirectory;
|
||||
Node *memDirectory;
|
||||
Memory::MemMgr *Memory;
|
||||
FileDescriptorTable *FileDescriptors;
|
||||
|
||||
public:
|
||||
Token CreateToken();
|
||||
bool TrustToken(Token token, TTL TrustLevel);
|
||||
bool AddTrustLevel(Token token, TTL TrustLevel);
|
||||
bool RemoveTrustLevel(Token token, TTL TrustLevel);
|
||||
bool UntrustToken(Token token);
|
||||
bool DestroyToken(Token token);
|
||||
bool IsTokenTrusted(Token token, TTL TrustLevel);
|
||||
bool IsTokenTrusted(Token token, int TrustLevel);
|
||||
int GetTokenTrustLevel(Token token);
|
||||
Security();
|
||||
~Security();
|
||||
void Rename(const char *name);
|
||||
void SetWorkingDirectory(Node *node);
|
||||
|
||||
PCB(class Task *ctx,
|
||||
PCB *Parent,
|
||||
const char *Name,
|
||||
TaskExecutionMode ExecutionMode,
|
||||
void *Image = nullptr,
|
||||
bool DoNotCreatePageTable = false,
|
||||
uint16_t UserID = -1,
|
||||
uint16_t GroupID = -1);
|
||||
|
||||
~PCB();
|
||||
};
|
||||
|
||||
class Task : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
Security SecurityManager;
|
||||
NewLock(SchedulerLock);
|
||||
NewLock(TaskingLock);
|
||||
|
||||
PID NextPID = 0;
|
||||
TID NextTID = 0;
|
||||
|
||||
@ -295,30 +289,76 @@ namespace Tasking
|
||||
std::atomic_size_t SchedulerTicks = 0;
|
||||
std::atomic_size_t LastTaskTicks = 0;
|
||||
std::atomic_int LastCore = 0;
|
||||
bool StopScheduler = false;
|
||||
std::atomic_bool StopScheduler = false;
|
||||
std::atomic_bool SchedulerUpdateTrapFrame = false;
|
||||
|
||||
bool InvalidPCB(PCB *pcb);
|
||||
bool InvalidTCB(TCB *tcb);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void RemoveThread(TCB *tcb);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void RemoveProcess(PCB *pcb);
|
||||
|
||||
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
|
||||
void UpdateUsage(TaskInfo *Info,
|
||||
TaskExecutionMode Mode,
|
||||
int Core);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
bool FindNewProcess(void *CPUDataPointer);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
bool GetNextAvailableThread(void *CPUDataPointer);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
bool GetNextAvailableProcess(void *CPUDataPointer);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
bool SchedulerSearchProcessThread(void *CPUDataPointer);
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void UpdateProcessStatus();
|
||||
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void WakeUpThreads();
|
||||
|
||||
#if defined(a64)
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void Schedule(CPU::x64::TrapFrame *Frame);
|
||||
|
||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||
#elif defined(a32)
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void Schedule(void *Frame);
|
||||
|
||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||
#elif defined(aa64)
|
||||
/**
|
||||
* @note This function is NOT thread safe
|
||||
*/
|
||||
void Schedule(CPU::aarch64::TrapFrame *Frame);
|
||||
|
||||
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
||||
#endif
|
||||
|
||||
@ -328,42 +368,62 @@ namespace Tasking
|
||||
size_t GetLastTaskTicks() { return LastTaskTicks.load(); }
|
||||
int GetLastCore() { return LastCore.load(); }
|
||||
std::vector<PCB *> GetProcessList() { return ProcessList; }
|
||||
Security *GetSecurityManager() { return &SecurityManager; }
|
||||
void CleanupProcessesThread();
|
||||
void Panic() { StopScheduler = true; }
|
||||
bool IsPanic() { return StopScheduler; }
|
||||
__always_inline inline void Schedule()
|
||||
|
||||
/**
|
||||
* Yield the current thread and switch
|
||||
* to another thread if available
|
||||
*/
|
||||
__always_inline inline void Yield()
|
||||
{
|
||||
/* This will trigger the IRQ16
|
||||
instantly so we won't execute
|
||||
the next instruction */
|
||||
#if defined(a86)
|
||||
asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */
|
||||
asmv("int $0x30");
|
||||
#elif defined(aa64)
|
||||
asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */
|
||||
asmv("svc #0x30");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current thread's trap frame
|
||||
* without switching to another thread
|
||||
*/
|
||||
__always_inline inline void UpdateFrame()
|
||||
{
|
||||
SchedulerUpdateTrapFrame = true;
|
||||
Yield();
|
||||
}
|
||||
|
||||
void SignalShutdown();
|
||||
void RevertProcessCreation(PCB *Process);
|
||||
void RevertThreadCreation(TCB *Thread);
|
||||
|
||||
void KillThread(TCB *tcb, enum KillErrorCodes Code)
|
||||
{
|
||||
tcb->Status = TaskStatus::Terminated;
|
||||
tcb->ExitCode = (int)Code;
|
||||
debug("Killing thread %s(%d) with exit code %d",
|
||||
tcb->Name, tcb->ID, Code);
|
||||
}
|
||||
|
||||
void KillProcess(PCB *pcb, enum KillErrorCodes Code)
|
||||
{
|
||||
pcb->Status = TaskStatus::Terminated;
|
||||
pcb->ExitCode = (int)Code;
|
||||
debug("Killing process %s(%d) with exit code %d",
|
||||
pcb->Name, pcb->ID, Code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the Current Process object
|
||||
* Get the Current Process object
|
||||
* @return PCB*
|
||||
*/
|
||||
PCB *GetCurrentProcess();
|
||||
|
||||
/**
|
||||
* @brief Get the Current Thread object
|
||||
* Get the Current Thread object
|
||||
* @return TCB*
|
||||
*/
|
||||
TCB *GetCurrentThread();
|
||||
@ -372,17 +432,17 @@ namespace Tasking
|
||||
|
||||
TCB *GetThreadByID(TID ID);
|
||||
|
||||
/** @brief Wait for process to terminate */
|
||||
/** Wait for process to terminate */
|
||||
void WaitForProcess(PCB *pcb);
|
||||
|
||||
/** @brief Wait for thread to terminate */
|
||||
/** Wait for thread to terminate */
|
||||
void WaitForThread(TCB *tcb);
|
||||
|
||||
void WaitForProcessStatus(PCB *pcb, TaskStatus Status);
|
||||
void WaitForThreadStatus(TCB *tcb, TaskStatus Status);
|
||||
|
||||
/**
|
||||
* @brief Sleep for a given amount of milliseconds
|
||||
* Sleep for a given amount of milliseconds
|
||||
*
|
||||
* @param Milliseconds Amount of milliseconds to sleep
|
||||
*/
|
||||
@ -390,9 +450,11 @@ namespace Tasking
|
||||
|
||||
PCB *CreateProcess(PCB *Parent,
|
||||
const char *Name,
|
||||
TaskTrustLevel TrustLevel,
|
||||
TaskExecutionMode TrustLevel,
|
||||
void *Image = nullptr,
|
||||
bool DoNotCreatePageTable = false);
|
||||
bool DoNotCreatePageTable = false,
|
||||
uint16_t UserID = UINT16_MAX,
|
||||
uint16_t GroupID = UINT16_MAX);
|
||||
|
||||
TCB *CreateThread(PCB *Parent,
|
||||
IP EntryPoint,
|
||||
@ -405,11 +467,17 @@ namespace Tasking
|
||||
|
||||
Task(const IP EntryPoint);
|
||||
~Task();
|
||||
|
||||
friend PCB;
|
||||
friend TCB;
|
||||
};
|
||||
}
|
||||
|
||||
#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code
|
||||
#define TEXIT(Code) TaskManager->GetCurrentThread()->ExitCode = Code
|
||||
#define thisProcess TaskManager->GetCurrentProcess()
|
||||
#define thisThread TaskManager->GetCurrentThread()
|
||||
|
||||
#define PEXIT(Code) thisProcess->ExitCode = Code
|
||||
#define TEXIT(Code) thisThread->ExitCode = Code
|
||||
|
||||
extern "C" void TaskingScheduler_OneShot(int TimeSlice);
|
||||
|
||||
|
Reference in New Issue
Block a user