Refactor task scheduler

This commit is contained in:
EnderIce2
2024-03-01 22:56:50 +02:00
parent 66ec562751
commit df457e8097
5 changed files with 472 additions and 477 deletions

150
include/scheduler.hpp Normal file
View File

@ -0,0 +1,150 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <task.hpp>
#include <lock.hpp>
namespace Tasking::Scheduler
{
class Base
{
public:
Task *ctx = nullptr;
std::atomic_size_t SchedulerTicks = 0;
std::atomic_size_t LastTaskTicks = 0;
std::atomic_int LastCore = 0;
std::atomic_bool StopScheduler = false;
std::atomic_bool SchedulerUpdateTrapFrame = false;
/**
* Remove a thread from the scheduler
*
* @note This function is NOT thread safe
* @note This function does not check if
* the thread is valid nor if it has
* Terminated status
*/
virtual bool RemoveThread(TCB *tcb)
{
assert(!"RemoveThread not implemented");
};
/**
* @note This function is NOT thread safe
*/
virtual bool RemoveProcess(PCB *pcb)
{
assert(!"RemoveProcess not implemented");
}
virtual PCB *GetProcessByID(TID ID)
{
assert(!"GetProcessByID not implemented");
}
virtual TCB *GetThreadByID(TID ID)
{
assert(!"GetThreadByID not implemented");
}
virtual std::list<PCB *> &GetProcessList()
{
assert(!"GetProcessList not implemented");
}
virtual void StartIdleProcess()
{
assert(!"StartIdleProcess not implemented");
}
virtual void StartScheduler()
{
assert(!"StartScheduler not implemented");
}
virtual void Yield()
{
assert(!"Yield not implemented");
}
virtual void PushProcess(PCB *pcb)
{
assert(!"PushProcess not implemented");
}
virtual void PopProcess(PCB *pcb)
{
assert(!"PopProcess not implemented");
}
Base(Task *_ctx)
: ctx(_ctx) {}
~Base() {}
};
class Custom : public Base,
public Interrupts::Handler
{
private:
NewLock(SchedulerLock);
public:
std::list<PCB *> ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
bool RemoveThread(TCB *tcb) final;
bool RemoveProcess(PCB *pcb) final;
PCB *GetProcessByID(TID ID) final;
TCB *GetThreadByID(TID ID) final;
std::list<PCB *> &GetProcessList() final;
void StartIdleProcess() final;
void StartScheduler() final;
void Yield() final;
void PushProcess(PCB *pcb) final;
void PopProcess(PCB *pcb) final;
void OneShot(int TimeSlice);
void UpdateUsage(TaskInfo *Info,
TaskExecutionMode Mode,
int Core);
bool FindNewProcess(void *CPUDataPointer);
bool GetNextAvailableThread(void *CPUDataPointer);
bool GetNextAvailableProcess(void *CPUDataPointer);
bool SchedulerSearchProcessThread(void *CPUDataPointer);
void UpdateProcessState();
void WakeUpThreads();
void CleanupTerminated();
void Schedule(CPU::TrapFrame *Frame);
void OnInterruptReceived(CPU::TrapFrame *Frame) final;
Custom(Task *ctx);
virtual ~Custom();
};
class RoundRobin : public Base,
public Interrupts::Handler
{
};
}

View File

@ -467,7 +467,7 @@ namespace Tasking
~PCB();
};
class Task : public Interrupts::Handler
class Task
{
private:
NewLock(SchedulerLock);
@ -476,114 +476,43 @@ namespace Tasking
PID NextPID = 0;
TID NextTID = 0;
std::list<PCB *> ProcessList;
PCB *KernelProcess = nullptr;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
std::atomic_size_t SchedulerTicks = 0;
std::atomic_size_t LastTaskTicks = 0;
std::atomic_int LastCore = 0;
std::atomic_bool StopScheduler = false;
std::atomic_bool SchedulerUpdateTrapFrame = false;
bool InvalidPCB(PCB *pcb);
bool InvalidTCB(TCB *tcb);
void *Scheduler = nullptr;
void *__sched_ctx = nullptr;
/**
* Remove a thread from the scheduler
*
* @note This function is NOT thread safe
* @note This function does not check if
* the thread is valid nor if it has
* Terminated status
*/
bool RemoveThread(TCB *tcb);
constexpr TaskArchitecture GetKArch()
{
#if defined(a64)
return x64;
#elif defined(a32)
return x32;
#elif defined(aa64)
return ARM64;
#endif
}
/**
* @note This function is NOT thread safe
*/
bool RemoveProcess(PCB *pcb);
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 UpdateProcessState();
/**
* @note This function is NOT thread safe
*/
void WakeUpThreads();
/**
* @note This function is NOT thread safe
*/
void CleanupTerminated();
/**
* @note This function is NOT thread safe
*/
void Schedule(CPU::TrapFrame *Frame);
void OnInterruptReceived(CPU::TrapFrame *Frame) final;
void PushProcess(PCB *pcb);
void PopProcess(PCB *pcb);
public:
void *GetScheduler() { return Scheduler; }
PCB *GetKernelProcess() { return KernelProcess; }
size_t GetSchedulerTicks() { return SchedulerTicks.load(); }
size_t GetLastTaskTicks() { return LastTaskTicks.load(); }
int GetLastCore() { return LastCore.load(); }
std::list<PCB *> GetProcessList() { return ProcessList; }
void Panic() { StopScheduler = true; }
bool IsPanic() { return StopScheduler; }
std::list<PCB *> GetProcessList();
void Panic();
bool IsPanic();
/**
* 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");
#elif defined(aa64)
asmv("svc #0x30");
#endif
}
void Yield();
/**
* Update the current thread's trap frame
* without switching to another thread
*/
__always_inline inline void UpdateFrame()
{
SchedulerUpdateTrapFrame = true;
Yield();
}
void UpdateFrame();
void SignalShutdown();
@ -670,6 +599,4 @@ namespace Tasking
#define thisProcess GetCurrentCPU()->CurrentProcess.load()
#define thisThread GetCurrentCPU()->CurrentThread.load()
extern "C" void TaskingScheduler_OneShot(int TimeSlice);
#endif // !__FENNIX_KERNEL_TASKING_H__