mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Updated tasking functions
This commit is contained in:
parent
aa45396d5b
commit
8cc9ff4ff3
351
Tasking/Task.cpp
351
Tasking/Task.cpp
@ -180,12 +180,135 @@ namespace Tasking
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableThread(void *CPUDataPointer)
|
||||||
{
|
{
|
||||||
SmartCriticalSection(SchedulerLock);
|
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++)
|
||||||
|
{
|
||||||
|
// Loop until we find the current thread from the process thread list.
|
||||||
|
if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread)
|
||||||
|
{
|
||||||
|
// Check if the next thread is valid. If not, we search until we find, but if we reach the end of the list, we go to the next process.
|
||||||
|
uint64_t tmpidx = i;
|
||||||
|
RetryAnotherThread:
|
||||||
|
TCB *thread = CurrentCPU->CurrentProcess->Threads[tmpidx + 1];
|
||||||
|
if (InvalidTCB(thread))
|
||||||
|
{
|
||||||
|
if (tmpidx > CurrentCPU->CurrentProcess->Threads.size())
|
||||||
|
break;
|
||||||
|
tmpidx++;
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Check if the thread is ready to be executed.
|
||||||
|
if (thread->Status != TaskStatus::Ready)
|
||||||
|
{
|
||||||
|
schedbg("Thread %d is not ready", thread->ID);
|
||||||
|
goto RetryAnotherThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything is fine, we can set the new thread as the current one.
|
||||||
|
CurrentCPU->CurrentThread = thread;
|
||||||
|
schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", thread->ID, thread->Parent->Name, CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size());
|
||||||
|
// Yay! We found a new thread to execute.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableProcess(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < ListProcess.size(); i++)
|
||||||
|
{
|
||||||
|
// Loop until we find the current process from the process list.
|
||||||
|
if (ListProcess[i] == CurrentCPU->CurrentProcess)
|
||||||
|
{
|
||||||
|
// Check if the next process is valid. If not, we search until we find.
|
||||||
|
uint64_t tmpidx = i;
|
||||||
|
RetryAnotherProcess:
|
||||||
|
PCB *pcb = ListProcess[tmpidx + 1];
|
||||||
|
if (InvalidPCB(pcb))
|
||||||
|
{
|
||||||
|
if (tmpidx > ListProcess.size())
|
||||||
|
break;
|
||||||
|
tmpidx++;
|
||||||
|
goto RetryAnotherProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcb->Status != TaskStatus::Ready)
|
||||||
|
goto RetryAnotherProcess;
|
||||||
|
|
||||||
|
// Everything good, now search for a thread.
|
||||||
|
for (uint64_t j = 0; j < pcb->Threads.size(); j++)
|
||||||
|
{
|
||||||
|
TCB *tcb = pcb->Threads[j];
|
||||||
|
if (InvalidTCB(tcb))
|
||||||
|
continue;
|
||||||
|
if (tcb->Status != TaskStatus::Ready)
|
||||||
|
continue;
|
||||||
|
// Success! We set as the current one and restore the stuff.
|
||||||
|
CurrentCPU->CurrentProcess = pcb;
|
||||||
|
CurrentCPU->CurrentThread = tcb;
|
||||||
|
schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", tcb->ID, tcb->Name, pcb->Threads.size(), ListProcess.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::SchedulerCleanupProcesses()
|
||||||
|
{
|
||||||
|
foreach (PCB *pcb in ListProcess)
|
||||||
|
{
|
||||||
|
if (InvalidPCB(pcb))
|
||||||
|
continue;
|
||||||
|
RemoveProcess(pcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::SchedulerSearchProcessThread(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
|
||||||
|
|
||||||
|
foreach (PCB *pcb in ListProcess)
|
||||||
|
{
|
||||||
|
if (InvalidPCB(pcb))
|
||||||
|
continue;
|
||||||
|
if (pcb->Status != TaskStatus::Ready)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Now do the thread search!
|
||||||
|
foreach (TCB *tcb in pcb->Threads)
|
||||||
|
{
|
||||||
|
if (InvalidTCB(tcb))
|
||||||
|
continue;
|
||||||
|
if (tcb->Status != TaskStatus::Ready)
|
||||||
|
continue;
|
||||||
|
// \o/ We found a new thread to execute.
|
||||||
|
CurrentCPU->CurrentProcess = pcb;
|
||||||
|
CurrentCPU->CurrentThread = tcb;
|
||||||
|
schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", tcb->ID, tcb->Parent->Name, pcb->Threads.size(), ListProcess.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::Schedule(CPU::x64::TrapFrame *Frame)
|
||||||
|
{
|
||||||
|
CriticalSection cs; // Just to be sure
|
||||||
|
if (cs.IsInterruptsEnabled())
|
||||||
|
warn("Interrupts are enabled in the scheduler!");
|
||||||
CPUData *CurrentCPU = GetCurrentCPU();
|
CPUData *CurrentCPU = GetCurrentCPU();
|
||||||
// debug("Scheduler called on CPU %d.", CurrentCPU->ID);
|
schedbg("Scheduler called on CPU %d.", CurrentCPU->ID);
|
||||||
// debug("%d: %ld%%", CurrentCPU->ID, GetUsage(CurrentCPU->ID));
|
schedbg("%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");
|
||||||
@ -226,108 +349,21 @@ namespace Tasking
|
|||||||
CurrentCPU->CurrentThread->Status = TaskStatus::Ready;
|
CurrentCPU->CurrentThread->Status = TaskStatus::Ready;
|
||||||
|
|
||||||
// Get next available thread from the list.
|
// Get next available thread from the list.
|
||||||
for (uint64_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++)
|
if (this->GetNextAvailableThread(CurrentCPU))
|
||||||
{
|
goto Success;
|
||||||
// Loop until we find the current thread from the process thread list.
|
|
||||||
if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread)
|
|
||||||
{
|
|
||||||
// Check if the next thread is valid. If not, we search until we find, but if we reach the end of the list, we go to the next process.
|
|
||||||
uint64_t tmpidx = i;
|
|
||||||
RetryAnotherThread:
|
|
||||||
TCB *thread = CurrentCPU->CurrentProcess->Threads[tmpidx + 1];
|
|
||||||
if (InvalidTCB(thread))
|
|
||||||
{
|
|
||||||
if (tmpidx > CurrentCPU->CurrentProcess->Threads.size())
|
|
||||||
break;
|
|
||||||
tmpidx++;
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Check if the thread is ready to be executed.
|
|
||||||
if (thread->Status != TaskStatus::Ready)
|
|
||||||
{
|
|
||||||
schedbg("Thread %d is not ready", thread->ID);
|
|
||||||
goto RetryAnotherThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything is fine, we can set the new thread as the current one.
|
|
||||||
CurrentCPU->CurrentThread = thread;
|
|
||||||
schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", thread->ID, thread->Parent->Name, CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size());
|
|
||||||
// Yay! We found a new thread to execute.
|
|
||||||
goto Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the last process didn't find a thread to execute, we search for a new process.
|
// If the last process didn't find a thread to execute, we search for a new process.
|
||||||
for (uint64_t i = 0; i < ListProcess.size(); i++)
|
if (this->GetNextAvailableProcess(CurrentCPU))
|
||||||
{
|
goto Success;
|
||||||
// Loop until we find the current process from the process list.
|
|
||||||
if (ListProcess[i] == CurrentCPU->CurrentProcess)
|
|
||||||
{
|
|
||||||
// Check if the next process is valid. If not, we search until we find.
|
|
||||||
uint64_t tmpidx = i;
|
|
||||||
RetryAnotherProcess:
|
|
||||||
PCB *pcb = ListProcess[tmpidx + 1];
|
|
||||||
if (InvalidPCB(pcb))
|
|
||||||
{
|
|
||||||
if (tmpidx > ListProcess.size())
|
|
||||||
break;
|
|
||||||
tmpidx++;
|
|
||||||
goto RetryAnotherProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcb->Status != TaskStatus::Ready)
|
|
||||||
goto RetryAnotherProcess;
|
|
||||||
|
|
||||||
// Everything good, now search for a thread.
|
|
||||||
for (uint64_t j = 0; j < pcb->Threads.size(); j++)
|
|
||||||
{
|
|
||||||
TCB *tcb = pcb->Threads[j];
|
|
||||||
if (InvalidTCB(tcb))
|
|
||||||
continue;
|
|
||||||
if (tcb->Status != TaskStatus::Ready)
|
|
||||||
continue;
|
|
||||||
// Success! We set as the current one and restore the stuff.
|
|
||||||
CurrentCPU->CurrentProcess = pcb;
|
|
||||||
CurrentCPU->CurrentThread = tcb;
|
|
||||||
schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", tcb->ID, tcb->Name, pcb->Threads.size(), ListProcess.size());
|
|
||||||
goto Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before checking from the beginning, we remove everything that is terminated.
|
// Before checking from the beginning, we remove everything that is terminated.
|
||||||
foreach (PCB *pcb in ListProcess)
|
this->SchedulerCleanupProcesses();
|
||||||
{
|
|
||||||
if (InvalidPCB(pcb))
|
|
||||||
continue;
|
|
||||||
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.
|
||||||
foreach (PCB *pcb in ListProcess)
|
if (SchedulerSearchProcessThread(CurrentCPU))
|
||||||
{
|
goto Success;
|
||||||
if (InvalidPCB(pcb))
|
else
|
||||||
continue;
|
goto Idle;
|
||||||
if (pcb->Status != TaskStatus::Ready)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Now do the thread search!
|
|
||||||
foreach (TCB *tcb in pcb->Threads)
|
|
||||||
{
|
|
||||||
if (InvalidTCB(tcb))
|
|
||||||
continue;
|
|
||||||
if (tcb->Status != TaskStatus::Ready)
|
|
||||||
continue;
|
|
||||||
// \o/ We found a new thread to execute.
|
|
||||||
CurrentCPU->CurrentProcess = pcb;
|
|
||||||
CurrentCPU->CurrentThread = tcb;
|
|
||||||
schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", tcb->ID, tcb->Parent->Name, pcb->Threads.size(), ListProcess.size());
|
|
||||||
goto Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
goto UnwantedReach; // This should never happen.
|
goto UnwantedReach; // This should never happen.
|
||||||
|
|
||||||
@ -401,23 +437,77 @@ namespace Tasking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||||
|
{
|
||||||
|
SmartCriticalSection(SchedulerLock);
|
||||||
|
this->Schedule(Frame);
|
||||||
|
}
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
__attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer)
|
__attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer)
|
||||||
{
|
{
|
||||||
fixme("unimplemented");
|
fixme("unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableThread(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableProcess(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::SchedulerCleanupProcesses()
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::SchedulerSearchProcessThread(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::Schedule(void *Frame)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
|
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
|
||||||
{
|
{
|
||||||
fixme("unimplemented");
|
fixme("unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
__attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer)
|
__attribute__((no_stack_protector)) bool Task::FindNewProcess(void *CPUDataPointer)
|
||||||
{
|
{
|
||||||
fixme("unimplemented");
|
fixme("unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableThread(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::GetNextAvailableProcess(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::SchedulerCleanupProcesses()
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) bool Task::SchedulerSearchProcessThread(void *CPUDataPointer)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((no_stack_protector)) void Task::Schedule(void *Frame)
|
||||||
|
{
|
||||||
|
fixme("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
|
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
|
||||||
{
|
{
|
||||||
fixme("unimplemented");
|
fixme("unimplemented");
|
||||||
@ -433,20 +523,15 @@ namespace Tasking
|
|||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
PCB *Task::GetCurrentProcess()
|
PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess; }
|
||||||
{
|
TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread; }
|
||||||
SmartCriticalSection(TaskingLock);
|
|
||||||
return GetCurrentCPU()->CurrentProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCB *Task::GetCurrentThread()
|
|
||||||
{
|
|
||||||
SmartCriticalSection(TaskingLock);
|
|
||||||
return GetCurrentCPU()->CurrentThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::WaitForProcess(PCB *pcb)
|
void Task::WaitForProcess(PCB *pcb)
|
||||||
{
|
{
|
||||||
|
if (!pcb)
|
||||||
|
return;
|
||||||
|
if (pcb->Status == TaskStatus::UnknownStatus)
|
||||||
|
return;
|
||||||
debug("Waiting for process \"%s\"(%d)", pcb->Name, pcb->ID);
|
debug("Waiting for process \"%s\"(%d)", pcb->Name, pcb->ID);
|
||||||
while (pcb->Status != TaskStatus::Terminated)
|
while (pcb->Status != TaskStatus::Terminated)
|
||||||
CPU::Halt();
|
CPU::Halt();
|
||||||
@ -454,6 +539,10 @@ namespace Tasking
|
|||||||
|
|
||||||
void Task::WaitForThread(TCB *tcb)
|
void Task::WaitForThread(TCB *tcb)
|
||||||
{
|
{
|
||||||
|
if (!tcb)
|
||||||
|
return;
|
||||||
|
if (tcb->Status == TaskStatus::UnknownStatus)
|
||||||
|
return;
|
||||||
debug("Waiting for thread \"%s\"(%d)", tcb->Name, tcb->ID);
|
debug("Waiting for thread \"%s\"(%d)", tcb->Name, tcb->ID);
|
||||||
while (tcb->Status != TaskStatus::Terminated)
|
while (tcb->Status != TaskStatus::Terminated)
|
||||||
CPU::Halt();
|
CPU::Halt();
|
||||||
@ -470,11 +559,7 @@ 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;
|
||||||
|
|
||||||
@ -492,7 +577,7 @@ namespace Tasking
|
|||||||
Thread->Argument0 = Argument0;
|
Thread->Argument0 = Argument0;
|
||||||
Thread->Argument1 = Argument1;
|
Thread->Argument1 = Argument1;
|
||||||
Thread->ExitCode = 0xdead;
|
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)));
|
||||||
Thread->Status = TaskStatus::Ready;
|
Thread->Status = TaskStatus::Ready;
|
||||||
|
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
@ -519,7 +604,7 @@ namespace Tasking
|
|||||||
Thread->Registers.rflags.AlwaysOne = 1;
|
Thread->Registers.rflags.AlwaysOne = 1;
|
||||||
Thread->Registers.rflags.IF = 1;
|
Thread->Registers.rflags.IF = 1;
|
||||||
Thread->Registers.rflags.ID = 1;
|
Thread->Registers.rflags.ID = 1;
|
||||||
Thread->Registers.rsp = (uint64_t)Thread->Stack;
|
Thread->Registers.rsp = ((uint64_t)Thread->Stack + STACK_SIZE);
|
||||||
POKE(uint64_t, Thread->Registers.rsp) = (uint64_t)ThreadDoExit;
|
POKE(uint64_t, Thread->Registers.rsp) = (uint64_t)ThreadDoExit;
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
@ -536,12 +621,16 @@ namespace Tasking
|
|||||||
Thread->Registers.rflags.AlwaysOne = 1;
|
Thread->Registers.rflags.AlwaysOne = 1;
|
||||||
Thread->Registers.rflags.IF = 1;
|
Thread->Registers.rflags.IF = 1;
|
||||||
Thread->Registers.rflags.ID = 1;
|
Thread->Registers.rflags.ID = 1;
|
||||||
Thread->Registers.rsp = (uint64_t)Thread->Stack;
|
Thread->Registers.rsp = ((uint64_t)Thread->Stack + STACK_SIZE);
|
||||||
/* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */
|
/* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */
|
||||||
for (uint64_t i = 0; i < TO_PAGES(STACK_SIZE); i++)
|
for (uint64_t i = 0; i < TO_PAGES(STACK_SIZE); i++)
|
||||||
Memory::Virtual().Map((void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)),
|
Memory::Virtual(Parent->PageTable).Map((void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)), (void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)), Memory::PTFlag::US);
|
||||||
(void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)),
|
|
||||||
Memory::PTFlag::US);
|
if (!Memory::Virtual(Parent->PageTable).Check((void *)Offset, Memory::PTFlag::US))
|
||||||
|
{
|
||||||
|
error("Offset is not user accessible");
|
||||||
|
Memory::Virtual(Parent->PageTable).Map((void *)Offset, (void *)Offset, Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
}
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
@ -550,7 +639,7 @@ namespace Tasking
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
error("Unknown elevation.");
|
error("Unknown elevation.");
|
||||||
KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - STACK_SIZE), TO_PAGES(STACK_SIZE));
|
KernelAllocator.FreePages(Thread->Stack, TO_PAGES(STACK_SIZE));
|
||||||
this->NextTID--;
|
this->NextTID--;
|
||||||
delete Thread;
|
delete Thread;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -577,6 +666,8 @@ namespace Tasking
|
|||||||
Thread->Info.Architecture = Architecture;
|
Thread->Info.Architecture = Architecture;
|
||||||
Thread->Info.Compatibility = Compatibility;
|
Thread->Info.Compatibility = Compatibility;
|
||||||
|
|
||||||
|
debug("Thread offset is %#lx (%#lx)", Thread->Offset, Thread->EntryPoint);
|
||||||
|
debug("Thread stack is %#lx-%#lx", Thread->Stack, (uint64_t)Thread->Stack + STACK_SIZE);
|
||||||
debug("Created thread \"%s\"(%d) in process \"%s\"(%d)",
|
debug("Created thread \"%s\"(%d) in process \"%s\"(%d)",
|
||||||
Thread->Name, Thread->ID,
|
Thread->Name, Thread->ID,
|
||||||
Thread->Parent->Name, Thread->Parent->ID);
|
Thread->Parent->Name, Thread->Parent->ID);
|
||||||
@ -594,11 +685,7 @@ 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 = 0xdead;
|
Process->ExitCode = 0xdead;
|
||||||
@ -621,8 +708,7 @@ namespace Tasking
|
|||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
||||||
memset(Process->PageTable, 0, PAGE_SIZE);
|
memset(Process->PageTable, 0, PAGE_SIZE);
|
||||||
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
memcpy(Process->PageTable, (void *)CPU::x64::readcr3().raw, PAGE_SIZE);
|
||||||
memcpy(Process->PageTable, (void *)cr3.raw, PAGE_SIZE);
|
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
@ -633,8 +719,10 @@ namespace Tasking
|
|||||||
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted);
|
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted);
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
||||||
// TODO: Do mapping for page table
|
memset(Process->PageTable, 0, PAGE_SIZE);
|
||||||
fixme("User process page table mapping not implemented.");
|
memcpy(Process->PageTable, (void *)CPU::x64::readcr3().raw, PAGE_SIZE);
|
||||||
|
fixme("User mode process page table is not implemented.");
|
||||||
|
// memcpy(Process->PageTable, (void *)UserspaceKernelOnlyPageTable, PAGE_SIZE);
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
@ -664,6 +752,7 @@ namespace Tasking
|
|||||||
}
|
}
|
||||||
Process->Info.Priority = 10;
|
Process->Info.Priority = 10;
|
||||||
|
|
||||||
|
debug("Process page table: %#lx", Process->PageTable);
|
||||||
debug("Created process \"%s\"(%d) in process \"%s\"(%d)",
|
debug("Created process \"%s\"(%d) in process \"%s\"(%d)",
|
||||||
Process->Name, Process->ID,
|
Process->Name, Process->ID,
|
||||||
Parent ? Process->Parent->Name : "None",
|
Parent ? Process->Parent->Name : "None",
|
||||||
|
@ -115,6 +115,8 @@ namespace Tasking
|
|||||||
trace("Setting priority of thread %s to %d", Name, priority);
|
trace("Setting priority of thread %s to %d", Name, priority);
|
||||||
Info.Priority = priority;
|
Info.Priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetExitCode() { return ExitCode; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PCB
|
struct PCB
|
||||||
@ -164,7 +166,7 @@ namespace Tasking
|
|||||||
PCB *IdleProcess = nullptr;
|
PCB *IdleProcess = nullptr;
|
||||||
TCB *IdleThread = nullptr;
|
TCB *IdleThread = nullptr;
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) static inline bool InvalidPCB(PCB *pcb)
|
__attribute__((no_stack_protector)) bool InvalidPCB(PCB *pcb)
|
||||||
{
|
{
|
||||||
if (pcb == (PCB *)0xffffffffffffffff)
|
if (pcb == (PCB *)0xffffffffffffffff)
|
||||||
return true;
|
return true;
|
||||||
@ -173,7 +175,7 @@ namespace Tasking
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((no_stack_protector)) static inline bool InvalidTCB(TCB *tcb)
|
__attribute__((no_stack_protector)) bool InvalidTCB(TCB *tcb)
|
||||||
{
|
{
|
||||||
if (tcb == (TCB *)0xffffffffffffffff)
|
if (tcb == (TCB *)0xffffffffffffffff)
|
||||||
return true;
|
return true;
|
||||||
@ -188,12 +190,19 @@ namespace Tasking
|
|||||||
void UpdateInfo(TaskInfo *Info, int Core);
|
void UpdateInfo(TaskInfo *Info, int Core);
|
||||||
|
|
||||||
bool FindNewProcess(void *CPUDataPointer);
|
bool FindNewProcess(void *CPUDataPointer);
|
||||||
|
bool GetNextAvailableThread(void *CPUDataPointer);
|
||||||
|
bool GetNextAvailableProcess(void *CPUDataPointer);
|
||||||
|
void SchedulerCleanupProcesses();
|
||||||
|
bool SchedulerSearchProcessThread(void *CPUDataPointer);
|
||||||
|
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
|
void Schedule(CPU::x64::TrapFrame *Frame);
|
||||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
|
void Schedule(void *Frame);
|
||||||
void OnInterruptReceived(void *Frame);
|
void OnInterruptReceived(void *Frame);
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
void Schedule(void *Frame);
|
||||||
void OnInterruptReceived(void *Frame);
|
void OnInterruptReceived(void *Frame);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user