Improved tasking

This commit is contained in:
Alex 2022-11-01 01:54:57 +02:00
parent 99606bed00
commit 0f16d63553
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
2 changed files with 186 additions and 59 deletions

View File

@ -1,7 +1,6 @@
#include <task.hpp> #include <task.hpp>
#include <lock.hpp> #include <lock.hpp>
#include <debug.h>
#include <smp.hpp> #include <smp.hpp>
#include "../kernel.h" #include "../kernel.h"
@ -22,7 +21,7 @@
#endif #endif
NewLock(TaskingLock); NewLock(TaskingLock);
NewLock(TaskingGetCurrentLock); NewLock(SchedulerLock);
namespace Tasking namespace Tasking
{ {
@ -41,7 +40,6 @@ namespace Tasking
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("IdleLoop:\n" asmv("IdleLoop:\n"
"call OneShot\n"
"hlt\n" "hlt\n"
"jmp IdleLoop\n"); "jmp IdleLoop\n");
#elif defined(__aarch64__) #elif defined(__aarch64__)
@ -51,6 +49,87 @@ namespace Tasking
#endif #endif
} }
__attribute__((no_stack_protector)) void Task::RemoveThread(TCB *Thread)
{
for (uint64_t i = 0; i < Thread->Parent->Threads.size(); i++)
if (Thread->Parent->Threads[i] == Thread)
{
trace("Thread \"%s\"(%d) removed from process \"%s\"(%d)",
Thread->Name, Thread->ID, Thread->Parent->Name, Thread->Parent->ID);
// Free memory
KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - STACK_SIZE), TO_PAGES(STACK_SIZE));
SecurityManager.DestroyToken(Thread->Security.UniqueToken);
delete Thread->Parent->Threads[i];
// Remove from the list
Thread->Parent->Threads.remove(i);
break;
}
}
__attribute__((no_stack_protector)) void Task::RemoveProcess(PCB *Process)
{
if (Process == nullptr)
return;
if (Process->Status == Terminated)
{
foreach (TCB *thread in Process->Threads)
RemoveThread(thread);
foreach (PCB *process in Process->Children)
RemoveProcess(process);
for (uint64_t i = 0; i < ListProcess.size(); i++)
{
if (ListProcess[i] == Process)
{
trace("Process \"%s\"(%d) removed from the list", Process->Name, Process->ID);
// Free memory
delete ListProcess[i]->IPCHandles;
SecurityManager.DestroyToken(ListProcess[i]->Security.UniqueToken);
KernelAllocator.FreePages((void *)ListProcess[i]->PageTable, TO_PAGES(PAGE_SIZE));
delete ListProcess[i];
// Remove from the list
ListProcess.remove(i);
break;
}
}
}
else
{
foreach (TCB *thread in Process->Threads)
if (thread->Status == Terminated)
RemoveThread(thread);
}
}
__attribute__((no_stack_protector)) void Task::UpdateInfo(TaskInfo *Info, int Core)
{
if (Info->Affinity[Core] == true)
{
// TODO: Not working
uint64_t CounterNow = CPU::Counter();
Info->OldUserTime = Info->CurrentUserTime;
Info->OldKernelTime = Info->CurrentKernelTime;
Info->CurrentUserTime = Info->UserTime;
Info->CurrentKernelTime = Info->KernelTime;
Info->UserTime = 0;
Info->KernelTime = 0;
Info->Usage[Core] = (Info->CurrentUserTime - Info->OldUserTime) + (Info->CurrentKernelTime - Info->OldKernelTime);
Info->Usage[Core] = (Info->Usage[Core] * 100) / (CounterNow - Info->SpawnTime);
Info->OldUserTime = Info->CurrentUserTime;
Info->OldKernelTime = Info->CurrentKernelTime;
Info->CurrentUserTime = Info->UserTime;
Info->CurrentKernelTime = Info->KernelTime;
}
}
#if defined(__amd64__) #if defined(__amd64__)
__attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer) __attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer)
{ {
@ -75,8 +154,8 @@ namespace Tasking
schedbg("Ready process (%s)%d", pcb->Name, pcb->ID); schedbg("Ready process (%s)%d", pcb->Name, pcb->ID);
break; break;
default: default:
schedbg("Process %s(%d) status %d", pcb->Name, pcb->ID, pcb->Status); schedbg("Process \"%s\"(%d) status %d", pcb->Name, pcb->ID, pcb->Status);
// RemoveProcess(pcb); // ignore for now RemoveProcess(pcb);
continue; continue;
} }
@ -103,9 +182,10 @@ namespace Tasking
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) __attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{ {
SmartCriticalSection(TaskingLock); SmartCriticalSection(SchedulerLock);
CPUData *CurrentCPU = GetCurrentCPU(); CPUData *CurrentCPU = GetCurrentCPU();
// debug("Scheduler called on CPU %d.", CurrentCPU->ID); // debug("Scheduler called on CPU %d.", CurrentCPU->ID);
// debug("%d: %ld%%", CurrentCPU->ID, GetUsage(CurrentCPU->ID));
schedbg("================================================================"); schedbg("================================================================");
schedbg("Status: 0-ukn | 1-rdy | 2-run | 3-wait | 4-term"); schedbg("Status: 0-ukn | 1-rdy | 2-run | 3-wait | 4-term");
@ -163,7 +243,7 @@ namespace Tasking
goto RetryAnotherThread; goto RetryAnotherThread;
} }
schedbg("%s(%d) and next thread is %s(%d)", CurrentCPU->CurrentProcess->Threads[i]->Name, CurrentCPU->CurrentProcess->Threads[i]->ID, thread->Name, thread->ID); schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)", CurrentCPU->CurrentProcess->Threads[i]->Name, CurrentCPU->CurrentProcess->Threads[i]->ID, thread->Name, thread->ID);
// Check if the thread is ready to be executed. // Check if the thread is ready to be executed.
if (thread->Status != TaskStatus::Ready) if (thread->Status != TaskStatus::Ready)
@ -223,7 +303,7 @@ namespace Tasking
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(pcb))
continue; continue;
// RemoveProcess(pcb); // comment this until i will find a way to handle properly vectors, the memory need to be 0ed after removing. RemoveProcess(pcb);
} }
// If we didn't find anything, we check from the start of the list. This is the last chance to find something or we go to idle. // If we didn't find anything, we check from the start of the list. This is the last chance to find something or we go to idle.
@ -249,37 +329,27 @@ namespace Tasking
} }
} }
} }
goto UnwantedReach; // This should never happen.
Idle: Idle:
{ {
// Should I remove processes that are no longer have any threads? Remove only from userspace?
if (IdleProcess == nullptr)
{
schedbg("Idle process created");
IdleProcess = CreateProcess(nullptr, (char *)"idle", TaskTrustLevel::Idle);
IdleThread = CreateThread(IdleProcess, reinterpret_cast<uint64_t>(IdleProcessLoop), 0);
}
CurrentCPU->CurrentProcess = IdleProcess; CurrentCPU->CurrentProcess = IdleProcess;
CurrentCPU->CurrentThread = IdleThread; CurrentCPU->CurrentThread = IdleThread;
goto Success;
*Frame = CurrentCPU->CurrentThread->Registers;
CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable});
CPU::x64::fxrstor(CurrentCPU->CurrentThread->FXRegion);
goto End;
} }
Success: Success:
{ {
schedbg("Success Prc:%s(%d) Thd:%s(%d)->RIP:%#lx-RSP:%#lx(STACK: %#lx)", schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d",
CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID, CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID,
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID);
CurrentCPU->CurrentThread->Registers.rip, CurrentCPU->CurrentThread->Registers.rsp, CurrentCPU->CurrentThread->Stack);
CurrentCPU->CurrentProcess->Status = TaskStatus::Running; CurrentCPU->CurrentProcess->Status = TaskStatus::Running;
CurrentCPU->CurrentThread->Status = TaskStatus::Running; CurrentCPU->CurrentThread->Status = TaskStatus::Running;
*Frame = CurrentCPU->CurrentThread->Registers; *Frame = CurrentCPU->CurrentThread->Registers;
CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable}); CPU::x64::writecr3({.raw = (uint64_t)CurrentCPU->CurrentProcess->PageTable});
CPU::x64::fxrstor(CurrentCPU->CurrentThread->FXRegion);
switch (CurrentCPU->CurrentProcess->Security.TrustLevel) switch (CurrentCPU->CurrentProcess->Security.TrustLevel)
{ {
@ -295,16 +365,19 @@ namespace Tasking
error("Unknown trust level %d.", CurrentCPU->CurrentProcess->Security.TrustLevel); error("Unknown trust level %d.", CurrentCPU->CurrentProcess->Security.TrustLevel);
break; break;
} }
CPU::x64::fxrstor(CurrentCPU->CurrentThread->FXRegion); goto End;
}
UnwantedReach:
{
warn("Unwanted reach!");
OneShot(100);
goto RealEnd;
} }
End: End:
{ {
// UpdateTimeUsed(&CurrentCPU->CurrentProcess->Info); UpdateInfo(&CurrentCPU->CurrentProcess->Info, CurrentCPU->ID);
// UpdateTimeUsed(&CurrentCPU->CurrentThread->Info); UpdateInfo(&CurrentCPU->CurrentThread->Info, CurrentCPU->ID);
// UpdateCPUUsage(&CurrentCPU->CurrentProcess->Info);
// UpdateCPUUsage(&CurrentCPU->CurrentThread->Info);
OneShot(CurrentCPU->CurrentThread->Info.Priority); OneShot(CurrentCPU->CurrentThread->Info.Priority);
schedbg("Scheduler end");
} }
schedbg("================================================================"); schedbg("================================================================");
schedbg("Technical Informations on Thread %s[%ld]:", CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID); schedbg("Technical Informations on Thread %s[%ld]:", CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID);
@ -322,6 +395,10 @@ namespace Tasking
schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx",
Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode); Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode);
schedbg("================================================================"); schedbg("================================================================");
RealEnd:
{
schedbg("Scheduler end");
}
} }
#elif defined(__i386__) #elif defined(__i386__)
@ -347,32 +424,45 @@ namespace Tasking
} }
#endif #endif
void ThreadDoExit(int Code) void ThreadDoExit()
{ {
SmartCriticalSection(TaskingLock); // TODO: How I can lock the scheduler without causing a deadlock?
CPUData *CPUData = GetCurrentCPU(); CPUData *CPUData = GetCurrentCPU();
CPUData->CurrentThread->Status = TaskStatus::Terminated; CPUData->CurrentThread->Status = TaskStatus::Terminated;
CPUData->CurrentThread->ExitCode = Code; debug("\"%s\"(%d) exited with code: %#lx", CPUData->CurrentThread->Name, CPUData->CurrentThread->ID, CPUData->CurrentThread->ExitCode);
debug("parent:%s tid:%d, code:%016p", CPUData->CurrentProcess->Name, CPUData->CurrentThread->ID, Code);
trace("Exiting thread %d(%s)...", CPUData->CurrentThread->ID, CPUData->CurrentThread->Name);
OneShot(CPUData->CurrentThread->Info.Priority);
CPU::Halt(true); CPU::Halt(true);
} }
PCB *Task::GetCurrentProcess() PCB *Task::GetCurrentProcess()
{ {
SmartCriticalSection(TaskingGetCurrentLock); SmartCriticalSection(TaskingLock);
return GetCurrentCPU()->CurrentProcess; return GetCurrentCPU()->CurrentProcess;
} }
TCB *Task::GetCurrentThread() TCB *Task::GetCurrentThread()
{ {
SmartCriticalSection(TaskingGetCurrentLock); SmartCriticalSection(TaskingLock);
return GetCurrentCPU()->CurrentThread; return GetCurrentCPU()->CurrentThread;
} }
void Task::WaitForProcess(PCB *pcb)
{
debug("Waiting for process \"%s\"(%d)", pcb->Name, pcb->ID);
while (pcb->Status != TaskStatus::Terminated)
CPU::Halt();
}
void Task::WaitForThread(TCB *tcb)
{
debug("Waiting for thread \"%s\"(%d)", tcb->Name, tcb->ID);
while (tcb->Status != TaskStatus::Terminated)
CPU::Halt();
}
TCB *Task::CreateThread(PCB *Parent, TCB *Task::CreateThread(PCB *Parent,
IP EntryPoint, IP EntryPoint,
Arg Argument0,
Arg Argument1,
IPOffset Offset, IPOffset Offset,
TaskArchitecture Architecture, TaskArchitecture Architecture,
TaskCompatibility Compatibility) TaskCompatibility Compatibility)
@ -380,7 +470,11 @@ namespace Tasking
SmartCriticalSection(TaskingLock); SmartCriticalSection(TaskingLock);
TCB *Thread = new TCB; TCB *Thread = new TCB;
if (Parent == nullptr) if (Parent == nullptr)
{
TaskingLock.Unlock();
Thread->Parent = this->GetCurrentProcess(); Thread->Parent = this->GetCurrentProcess();
TaskingLock.Lock(__FUNCTION__);
}
else else
Thread->Parent = Parent; Thread->Parent = Parent;
@ -395,13 +489,17 @@ namespace Tasking
strcpy(Thread->Name, Parent->Name); strcpy(Thread->Name, Parent->Name);
Thread->EntryPoint = EntryPoint; Thread->EntryPoint = EntryPoint;
Thread->Offset = Offset; Thread->Offset = Offset;
Thread->ExitCode = 0xdeadbeef; Thread->Argument0 = Argument0;
Thread->Argument1 = Argument1;
Thread->ExitCode = 0xdead;
Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE); Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
Thread->Status = TaskStatus::Ready; Thread->Status = TaskStatus::Ready;
#if defined(__amd64__) #if defined(__amd64__)
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
Thread->Registers.rip = (EntryPoint + Offset); Thread->Registers.rip = (EntryPoint + Offset);
Thread->Registers.rdi = Argument0;
Thread->Registers.rsi = Argument1;
#elif defined(__i386__) #elif defined(__i386__)
#elif defined(__aarch64__) #elif defined(__aarch64__)
#endif #endif
@ -462,11 +560,8 @@ namespace Tasking
Thread->Security.TrustLevel = Parent->Security.TrustLevel; Thread->Security.TrustLevel = Parent->Security.TrustLevel;
// Thread->Security.UniqueToken = SecurityManager.CreateToken(); // Thread->Security.UniqueToken = SecurityManager.CreateToken();
Thread->Info.SpawnTime = 0; Thread->Info = {};
Thread->Info.UsedTime = 0; Thread->Info.SpawnTime = CPU::Counter();
Thread->Info.OldUsedTime = 0;
Thread->Info.OldSystemTime = 0;
Thread->Info.CurrentSystemTime = 0;
Thread->Info.Year = 0; Thread->Info.Year = 0;
Thread->Info.Month = 0; Thread->Info.Month = 0;
Thread->Info.Day = 0; Thread->Info.Day = 0;
@ -476,13 +571,15 @@ namespace Tasking
for (int i = 0; i < MAX_CPU; i++) for (int i = 0; i < MAX_CPU; i++)
{ {
Thread->Info.Usage[i] = 0; Thread->Info.Usage[i] = 0;
Thread->Info.Affinity[i] = 0; Thread->Info.Affinity[i] = true;
} }
Thread->Info.Priority = 0; Thread->Info.Priority = 10;
Thread->Info.Architecture = Architecture; Thread->Info.Architecture = Architecture;
Thread->Info.Compatibility = Compatibility; Thread->Info.Compatibility = Compatibility;
debug("Created thread %d(%s) in process %d(%s)", Thread->ID, Thread->Name, Thread->Parent->ID, Thread->Parent->Name); debug("Created thread \"%s\"(%d) in process \"%s\"(%d)",
Thread->Name, Thread->ID,
Thread->Parent->Name, Thread->Parent->ID);
Parent->Threads.push_back(Thread); Parent->Threads.push_back(Thread);
return Thread; return Thread;
@ -497,10 +594,14 @@ namespace Tasking
Process->ID = this->NextPID++; Process->ID = this->NextPID++;
strcpy(Process->Name, Name); strcpy(Process->Name, Name);
if (Parent == nullptr) if (Parent == nullptr)
{
TaskingLock.Unlock();
Process->Parent = this->GetCurrentProcess(); Process->Parent = this->GetCurrentProcess();
TaskingLock.Lock(__FUNCTION__);
}
else else
Process->Parent = Parent; Process->Parent = Parent;
Process->ExitCode = 0xdeadbeef; Process->ExitCode = 0xdead;
Process->Status = TaskStatus::Ready; Process->Status = TaskStatus::Ready;
Process->Security.TrustLevel = TrustLevel; Process->Security.TrustLevel = TrustLevel;
@ -548,11 +649,8 @@ namespace Tasking
} }
} }
Process->Info.SpawnTime = 0; Process->Info = {};
Process->Info.UsedTime = 0; Process->Info.SpawnTime = CPU::Counter();
Process->Info.OldUsedTime = 0;
Process->Info.OldSystemTime = 0;
Process->Info.CurrentSystemTime = 0;
Process->Info.Year = 0; Process->Info.Year = 0;
Process->Info.Month = 0; Process->Info.Month = 0;
Process->Info.Day = 0; Process->Info.Day = 0;
@ -562,11 +660,14 @@ namespace Tasking
for (int i = 0; i < MAX_CPU; i++) for (int i = 0; i < MAX_CPU; i++)
{ {
Process->Info.Usage[i] = 0; Process->Info.Usage[i] = 0;
Process->Info.Affinity[i] = 0; Process->Info.Affinity[i] = true;
} }
Process->Info.Priority = 0; Process->Info.Priority = 10;
debug("Created process %d(%s) in process %d(%s)", Process->ID, Process->Name, Parent ? Process->Parent->ID : 0, Parent ? Process->Parent->Name : "None"); debug("Created process \"%s\"(%d) in process \"%s\"(%d)",
Process->Name, Process->ID,
Parent ? Process->Parent->Name : "None",
Parent ? Process->Parent->ID : 0);
if (Parent) if (Parent)
Parent->Children.push_back(Process); Parent->Children.push_back(Process);
@ -594,9 +695,8 @@ namespace Tasking
#elif defined(__aarch64__) #elif defined(__aarch64__)
TaskArchitecture Arch = TaskArchitecture::ARM64; TaskArchitecture Arch = TaskArchitecture::ARM64;
#endif #endif
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel); PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
TCB *kthrd = CreateThread(kproc, EntryPoint, 0, Arch); TCB *kthrd = CreateThread(kproc, EntryPoint, 0, 0, 0, Arch);
kthrd->Rename("Main Thread"); kthrd->Rename("Main Thread");
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name); debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
TaskingLock.Lock(__FUNCTION__); TaskingLock.Lock(__FUNCTION__);
@ -624,6 +724,10 @@ namespace Tasking
#endif #endif
TaskingLock.Unlock(); TaskingLock.Unlock();
this->IPCManager = new InterProcessCommunication::IPC; this->IPCManager = new InterProcessCommunication::IPC;
IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Idle);
IdleThread = CreateThread(IdleProcess, reinterpret_cast<uint64_t>(IdleProcessLoop));
IdleThread->Rename("Idle Thread");
IdleThread->SetPriority(1);
TaskingLock.Lock(__FUNCTION__); TaskingLock.Lock(__FUNCTION__);
debug("Tasking Started"); debug("Tasking Started");
} }

View File

@ -8,10 +8,12 @@
#include <memory.hpp> #include <memory.hpp>
#include <hashmap.hpp> #include <hashmap.hpp>
#include <ipc.hpp> #include <ipc.hpp>
#include <debug.h>
namespace Tasking namespace Tasking
{ {
typedef unsigned long IP; typedef unsigned long IP;
typedef unsigned long Arg;
typedef unsigned long IPOffset; typedef unsigned long IPOffset;
typedef unsigned long UPID; typedef unsigned long UPID;
typedef unsigned long UTID; typedef unsigned long UTID;
@ -62,8 +64,10 @@ namespace Tasking
struct TaskInfo struct TaskInfo
{ {
uint64_t SpawnTime = 0, UsedTime = 0, OldUsedTime = 0; uint64_t SpawnTime = 0;
uint64_t OldSystemTime = 0, CurrentSystemTime = 0; uint64_t OldUserTime = 0, CurrentUserTime = 0;
uint64_t OldKernelTime = 0, CurrentKernelTime = 0;
uint64_t KernelTime = 0, UserTime = 0;
uint64_t Year, Month, Day, Hour, Minute, Second; uint64_t Year, Month, Day, Hour, Minute, Second;
uint64_t Usage[256]; // MAX_CPU uint64_t Usage[256]; // MAX_CPU
bool Affinity[256]; // MAX_CPU bool Affinity[256]; // MAX_CPU
@ -79,6 +83,8 @@ namespace Tasking
struct PCB *Parent; struct PCB *Parent;
IP EntryPoint; IP EntryPoint;
IPOffset Offset; IPOffset Offset;
Arg Argument0;
Arg Argument1;
int ExitCode; int ExitCode;
void *Stack; void *Stack;
TaskStatus Status; TaskStatus Status;
@ -95,6 +101,7 @@ namespace Tasking
void Rename(const char *name) void Rename(const char *name)
{ {
trace("Renaming thread %s to %s", Name, name);
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
Name[i] = name[i]; Name[i] = name[i];
@ -105,6 +112,7 @@ namespace Tasking
void SetPriority(int priority) void SetPriority(int priority)
{ {
trace("Setting priority of thread %s to %d", Name, priority);
Info.Priority = priority; Info.Priority = priority;
} }
}; };
@ -174,6 +182,11 @@ namespace Tasking
return false; return false;
} }
void RemoveThread(TCB *tcb);
void RemoveProcess(PCB *pcb);
void UpdateInfo(TaskInfo *Info, int Core);
bool FindNewProcess(void *CPUDataPointer); bool FindNewProcess(void *CPUDataPointer);
#if defined(__amd64__) #if defined(__amd64__)
@ -185,6 +198,8 @@ namespace Tasking
#endif #endif
public: public:
long GetUsage(int Core) { return 100 - IdleProcess->Info.Usage[Core]; }
/** /**
* @brief Get the Current Process object * @brief Get the Current Process object
* @return PCB* * @return PCB*
@ -197,12 +212,20 @@ namespace Tasking
*/ */
TCB *GetCurrentThread(); TCB *GetCurrentThread();
/** @brief Wait for process to terminate */
void WaitForProcess(PCB *pcb);
/** @brief Wait for thread to terminate */
void WaitForThread(TCB *tcb);
PCB *CreateProcess(PCB *Parent, PCB *CreateProcess(PCB *Parent,
const char *Name, const char *Name,
TaskTrustLevel TrustLevel); TaskTrustLevel TrustLevel);
TCB *CreateThread(PCB *Parent, TCB *CreateThread(PCB *Parent,
IP EntryPoint, IP EntryPoint,
Arg Argument0 = 0,
Arg Argument1 = 0,
IPOffset Offset = 0, IPOffset Offset = 0,
TaskArchitecture Architecture = TaskArchitecture::x64, TaskArchitecture Architecture = TaskArchitecture::x64,
TaskCompatibility Compatibility = TaskCompatibility::Native); TaskCompatibility Compatibility = TaskCompatibility::Native);