121 lines
3.2 KiB
C++
121 lines
3.2 KiB
C++
|
#include "Tier1/CRoundRobinScheduler.h"
|
||
|
using namespace cb;
|
||
|
|
||
|
extern "C" {
|
||
|
#include "Tier0/panic.h"
|
||
|
#include "Tier0/kstdio.h"
|
||
|
#include "Tier0/heap.h"
|
||
|
}
|
||
|
|
||
|
void CRoundRobinScheduler::Enable(bool Enabled)
|
||
|
{
|
||
|
m_iTaskQueuePosition = 0;
|
||
|
m_PrioritizedTask = 0;
|
||
|
}
|
||
|
|
||
|
__attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip)
|
||
|
{
|
||
|
// A wild magic value appears!
|
||
|
esp += 12;
|
||
|
|
||
|
volatile u32 NewEBP, NewESP, NewEIP, Directory;
|
||
|
|
||
|
if (m_TaskQueue.GetSize() < 1)
|
||
|
PANIC("No tasks in queue!");
|
||
|
|
||
|
// Fetch next task.
|
||
|
CTask *NextTask;
|
||
|
/*if (m_PrioritizedTask != 0)
|
||
|
{
|
||
|
NextTask = m_PrioritizedTask;
|
||
|
m_PrioritizedTask = 0;
|
||
|
}
|
||
|
else
|
||
|
{*/
|
||
|
do {
|
||
|
m_iTaskQueuePosition++;
|
||
|
|
||
|
if (m_iTaskQueuePosition >= m_TaskQueue.GetSize())
|
||
|
// Something happened - restart the queue
|
||
|
m_iTaskQueuePosition = 0;
|
||
|
NextTask = m_TaskQueue[m_iTaskQueuePosition];
|
||
|
}
|
||
|
while (NextTask->GetStatus() != ETS_RUNNING);
|
||
|
//}
|
||
|
if (m_CurrentTask->GetPID() == NextTask->GetPID())
|
||
|
return;
|
||
|
|
||
|
//kprintf("switching from %x %x %x (%i to %i)\n", eip, esp, ebp, m_CurrentTask->GetPID(), NextTask->GetPID());
|
||
|
|
||
|
//kprintf("[i] %i -> %i (%x)\n", m_CurrentTask->GetPID(), NextTask->GetPID(), NextTask);
|
||
|
|
||
|
// Read task details
|
||
|
NewEBP = NextTask->GetEBP();
|
||
|
NewESP = NextTask->GetESP();
|
||
|
NewEIP = NextTask->GetEIP();
|
||
|
if (!NewEIP || !NewESP || !NewEBP)
|
||
|
{
|
||
|
//kprintf("null %x %x %x\n", NewEIP, NewESP, NewEBP);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Save current task details
|
||
|
m_CurrentTask->SetEBP(ebp);
|
||
|
m_CurrentTask->SetESP(esp);
|
||
|
|
||
|
// Return point
|
||
|
volatile u32 ReturnPoint = eip;
|
||
|
|
||
|
m_CurrentTask->SetEIP(ReturnPoint);
|
||
|
// Switch to next task
|
||
|
m_CurrentTask = NextTask;
|
||
|
|
||
|
Directory = NextTask->GetPageDirectoryPhysicalAddress();
|
||
|
//kprintf("[i] I was told to jump to %x (%x %x); %x\n", NewEIP, NewESP,
|
||
|
// NewEBP, Directory);
|
||
|
//for(;;){}
|
||
|
interrupts_irq_finish(0);
|
||
|
|
||
|
__asm__ volatile("movl %1, %%esp\n"
|
||
|
"movl %2, %%ebp\n"
|
||
|
"movl %3, %%cr3\n"
|
||
|
"movl %0, %%ecx\n"
|
||
|
"jmp *%%ecx" ::
|
||
|
"r"(NewEIP),
|
||
|
"r"(NewESP),
|
||
|
"r"(NewEBP),
|
||
|
"r"(Directory));
|
||
|
}
|
||
|
|
||
|
void CRoundRobinScheduler::AddTask(CTask *Task)
|
||
|
{
|
||
|
m_TaskQueue.Push(Task);
|
||
|
if (m_TaskQueue.GetSize() == 1)
|
||
|
m_CurrentTask = Task;
|
||
|
}
|
||
|
|
||
|
CTask *CRoundRobinScheduler::GetCurrentTask(void)
|
||
|
{
|
||
|
return m_CurrentTask;
|
||
|
}
|
||
|
|
||
|
void CRoundRobinScheduler::PrioritizeTask(CTask *Task)
|
||
|
{
|
||
|
m_PrioritizedTask = Task;
|
||
|
}
|
||
|
|
||
|
void CRoundRobinScheduler::SetSemaphoreAvailable(CSemaphore *Semaphore)
|
||
|
{
|
||
|
u32 Physical = GetCurrentTask()->GetPageDirectory()->
|
||
|
Translate((u32)Semaphore);
|
||
|
for (u32 i = 0; i < m_TaskQueue.GetSize(); i++)
|
||
|
{
|
||
|
CTask *Task = m_TaskQueue[i];
|
||
|
if (Task->GetStatus() == ETS_WAITING_FOR_SEMAPHORE &&
|
||
|
Task->GetStatusData() == Physical)
|
||
|
{
|
||
|
Task->Enable();
|
||
|
}
|
||
|
}
|
||
|
}
|