Some scheduler fixes.
parent
11cf26eb54
commit
164ea30d44
|
@ -1,7 +1,7 @@
|
|||
#Sun May 08 13:56:50 CEST 2011
|
||||
#Sun May 08 17:23:22 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/PATH/delimiter=;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/PATH/operation=replace
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/PATH/value=C\:\\cygwin\\bin;C\:\\Windows\\system32;C\:\\Windows;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/PATH/value=C\:\\Development\\qemu;C\:\\cygwin\\bin;C\:\\Windows\\system32;C\:\\Windows;
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/append=true
|
||||
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/appendContributed=true
|
||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@
|
|||
# Seriously.
|
||||
#
|
||||
# Fuck M4. I do this because it's probably the most portable way, and I don't
|
||||
# wan't to write Yet Another Compile System because fuck that shit. I could
|
||||
# want to write Yet Another Compile System because fuck that shit. I could
|
||||
# use cmake but I don't know whether it is flexible enough. It probably is
|
||||
# but whatever. I wrote this piece of shit below, let's just keep it that
|
||||
# way. There are better way to do the hthings I do below, but who gives a
|
||||
|
|
|
@ -9,13 +9,16 @@ namespace cb {
|
|||
public:
|
||||
void Enable(bool Enabled);
|
||||
void AddTask(CTask *Task);
|
||||
void NextTask(void);
|
||||
void NextTask(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip);
|
||||
CTask *GetCurrentTask(void);
|
||||
void SetSemaphoreAvailable(CSemaphore *Semaphore);
|
||||
void PrioritizeTask(CTask *Task);
|
||||
private:
|
||||
CTask *m_CurrentTask;
|
||||
CLinearList<CTask *> m_TaskQueue;
|
||||
u32 m_iTaskQueuePosition;
|
||||
|
||||
CTask *m_PrioritizedTask;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "Tier1/IScheduler.h"
|
||||
#include "Tier1/CSemaphore.h"
|
||||
|
||||
#define CSCHEDULER_INTERRUPT_YIELD 0x99
|
||||
|
||||
extern "C" {
|
||||
#include "Tier0/interrupts.h"
|
||||
}
|
||||
|
@ -16,17 +18,21 @@ namespace cb {
|
|||
CTask *Task;
|
||||
struct STaskQueueNode *Next;
|
||||
} TTaskQueueNode;
|
||||
class CScheduler {
|
||||
class CScheduler{
|
||||
private:
|
||||
IScheduler *m_CurrentScheduler;
|
||||
|
||||
static bool TimerTick(u32 Extra);
|
||||
static void TimerTick(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip);
|
||||
static void Yield(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip);
|
||||
|
||||
static u32 m_NumTicks;
|
||||
public:
|
||||
CScheduler(void);
|
||||
static void Enable(void);
|
||||
static void AddTask(CTask *Task);
|
||||
static CTask *GetCurrentTask(void);
|
||||
static void NextTask(void);
|
||||
static void NextTask();
|
||||
static void PrioritizeTask(CTask *Task);
|
||||
|
||||
static void DispatchAvailableSemaphore(CSemaphore *Semaphore);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
|||
|
||||
namespace cb {
|
||||
class CSemaphore {
|
||||
private:
|
||||
protected:
|
||||
T_ATOMIC m_Available;
|
||||
public:
|
||||
CSemaphore(u32 Available = 1);
|
||||
|
|
|
@ -3,34 +3,46 @@
|
|||
|
||||
#include "Tier1/CInterruptDispatcher.h"
|
||||
#include "Tier1/Util/CLinearList.h"
|
||||
#include "Tier1/CTask.h"
|
||||
#include "Tier1/CSemaphore.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace cb {
|
||||
typedef bool(*TTimerCallback)(u32);
|
||||
typedef void(*TTimerFastHook)(u32, u32, u32, u32, u32, u32, u32, u32, u32);
|
||||
typedef struct {
|
||||
TTimerCallback Callback;
|
||||
u32 Interval;
|
||||
s32 Times;
|
||||
u32 NextCall;
|
||||
u32 Extra;
|
||||
CTask *Task;
|
||||
} TCallbackInfo;
|
||||
class CTimer {
|
||||
public:
|
||||
static void Create(u32 Interval, s32 Times, TTimerCallback Callback,
|
||||
u32 Extra = 0);
|
||||
// This is like ::Create, but faster, and there can only be one, and it's fixed interval
|
||||
static void SetFastTimerHook(TTimerFastHook Hook);
|
||||
inline static u32 GetTicks(void)
|
||||
{
|
||||
if (!m_bInitialized)
|
||||
Initialize();
|
||||
return m_nTicks;
|
||||
m_GetTicksSemaphore.Acquire();
|
||||
volatile u32 Ticks = m_nTicks;
|
||||
m_GetTicksSemaphore.Release();
|
||||
return Ticks;
|
||||
}
|
||||
private:
|
||||
static CLinearList<TCallbackInfo> m_Callbacks;
|
||||
volatile static u32 m_nTicks;
|
||||
static void Initialize(void);
|
||||
static void Dispatch(void *Registers);
|
||||
static void Dispatch(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip);
|
||||
static bool m_bInitialized;
|
||||
static TTimerFastHook m_FastHook;
|
||||
|
||||
static CSemaphore m_GetTicksSemaphore;
|
||||
|
||||
// Called when the number of ticks is just about to overflow.
|
||||
// Reschedules all the callbacks.
|
||||
static void Reschedule(void);
|
||||
|
|
|
@ -9,9 +9,10 @@ namespace cb {
|
|||
public:
|
||||
virtual void Enable(bool Enabled) = 0;
|
||||
virtual void AddTask(CTask *Task) = 0;
|
||||
virtual void NextTask(void) = 0;
|
||||
virtual void NextTask(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip) = 0;
|
||||
virtual CTask *GetCurrentTask(void) = 0;
|
||||
virtual void SetSemaphoreAvailable(CSemaphore *Semaphore) = 0;
|
||||
virtual void PrioritizeTask(CTask *Task) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ extern "C" {
|
|||
#include "Tier0/heap.h"
|
||||
#include "Tier0/panic.h"
|
||||
#include "Tier0/kstdlib.h"
|
||||
#include "Tier0/kstdio.h"
|
||||
};
|
||||
|
||||
namespace cb {
|
||||
|
@ -96,12 +97,18 @@ namespace cb {
|
|||
|
||||
template <class _T> _T &CLinearList<_T>::operator[](u32 Index)
|
||||
{
|
||||
ASSERT(m_Data != 0);
|
||||
ASSERT(m_Data != 0);
|
||||
TLinearListNode *Node = m_Data;
|
||||
for (u32 i = 0; i < Index; i++)
|
||||
{
|
||||
Node = Node->Next;
|
||||
ASSERT(Node != 0);
|
||||
//ASSERT(Node != 0);
|
||||
if (Node == 0)
|
||||
{
|
||||
kprintf("fail\n");
|
||||
__asm__ volatile("cli");
|
||||
for(;;){}
|
||||
}
|
||||
}
|
||||
|
||||
return Node->Data;
|
||||
|
@ -164,10 +171,25 @@ namespace cb {
|
|||
m_SizeCacheValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(m_Data != 0);
|
||||
|
||||
if (Index == 0)
|
||||
{
|
||||
ASSERT(m_Data != 0);
|
||||
|
||||
TLinearListNode *ToBeDeleted = m_Data;
|
||||
TLinearListNode *NodeAfter = m_Data->Next;
|
||||
m_Data = NodeAfter;
|
||||
|
||||
kfree((void*)ToBeDeleted);
|
||||
|
||||
m_SizeCacheValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
TLinearListNode *NodeBefore = m_Data;
|
||||
for (u32 i = 0; i < Index - 1; i++)
|
||||
for (s32 i = 0; i < (s32)Index - 1; i++)
|
||||
{
|
||||
NodeBefore = NodeBefore->Next;
|
||||
ASSERT(NodeBefore != 0);
|
||||
|
|
|
@ -66,8 +66,12 @@ void CKernel::Start(void)
|
|||
else
|
||||
{
|
||||
for (;;) {
|
||||
CScheduler::GetCurrentTask()->Sleep(1000);
|
||||
kprintf("[i] Hello! I'm the child process.\n");
|
||||
//CScheduler::GetCurrentTask()->Sleep(1000);
|
||||
for (volatile u32 i = 0; i < 14000; i++)
|
||||
{
|
||||
for (volatile u32 j = 0; j < 650; j++){}
|
||||
}
|
||||
kprintf("[i] Hello! I'm the child process %i.\n", CTimer::GetTicks());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,30 +10,43 @@ extern "C" {
|
|||
void CRoundRobinScheduler::Enable(bool Enabled)
|
||||
{
|
||||
m_iTaskQueuePosition = 0;
|
||||
m_PrioritizedTask = 0;
|
||||
}
|
||||
|
||||
__attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
|
||||
__attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip)
|
||||
{
|
||||
volatile u32 NewEBP, NewESP, NewEIP, EBP, ESP, Directory;
|
||||
// A wild magic value appears!
|
||||
esp += 12;
|
||||
|
||||
volatile u32 NewEBP, NewESP, NewEIP, Directory;
|
||||
|
||||
if (m_TaskQueue.GetSize() == 0)
|
||||
if (m_TaskQueue.GetSize() < 1)
|
||||
PANIC("No tasks in queue!");
|
||||
|
||||
// Fetch next task.
|
||||
CTask *NextTask;
|
||||
do {
|
||||
m_iTaskQueuePosition++;
|
||||
|
||||
if (m_iTaskQueuePosition >= m_TaskQueue.GetSize())
|
||||
// Something happened - restart the queue
|
||||
m_iTaskQueuePosition = 0;
|
||||
NextTask = m_TaskQueue[m_iTaskQueuePosition];
|
||||
/*if (m_PrioritizedTask != 0)
|
||||
{
|
||||
NextTask = m_PrioritizedTask;
|
||||
m_PrioritizedTask = 0;
|
||||
}
|
||||
while (NextTask->GetStatus() != ETS_RUNNING);
|
||||
|
||||
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
|
||||
|
@ -47,26 +60,18 @@ __attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
|
|||
}
|
||||
|
||||
// Save current task details
|
||||
__asm__ volatile("mov %%esp, %0" : "=r"(ESP));
|
||||
__asm__ volatile("mov %%ebp, %0" : "=r"(EBP));
|
||||
m_CurrentTask->SetEBP(EBP);
|
||||
m_CurrentTask->SetESP(ESP);
|
||||
m_CurrentTask->SetEBP(ebp);
|
||||
m_CurrentTask->SetESP(esp);
|
||||
|
||||
// Return point
|
||||
volatile u32 ReturnPoint = ctask_geteip();
|
||||
|
||||
if (ReturnPoint == 0xFEEDFACE)
|
||||
{
|
||||
//We are in the next task already
|
||||
return;
|
||||
}
|
||||
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,
|
||||
//kprintf("[i] I was told to jump to %x (%x %x); %x\n", NewEIP, NewESP,
|
||||
// NewEBP, Directory);
|
||||
//for(;;){}
|
||||
interrupts_irq_finish(0);
|
||||
|
@ -75,7 +80,6 @@ __attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
|
|||
"movl %2, %%ebp\n"
|
||||
"movl %3, %%cr3\n"
|
||||
"movl %0, %%ecx\n"
|
||||
"movl $0xFEEDFACE, %%eax\n"
|
||||
"jmp *%%ecx" ::
|
||||
"r"(NewEIP),
|
||||
"r"(NewESP),
|
||||
|
@ -95,6 +99,11 @@ CTask *CRoundRobinScheduler::GetCurrentTask(void)
|
|||
return m_CurrentTask;
|
||||
}
|
||||
|
||||
void CRoundRobinScheduler::PrioritizeTask(CTask *Task)
|
||||
{
|
||||
m_PrioritizedTask = Task;
|
||||
}
|
||||
|
||||
void CRoundRobinScheduler::SetSemaphoreAvailable(CSemaphore *Semaphore)
|
||||
{
|
||||
u32 Physical = GetCurrentTask()->GetPageDirectory()->
|
||||
|
|
|
@ -3,14 +3,17 @@ using namespace cb;
|
|||
|
||||
#include "Tier1/CRoundRobinScheduler.h"
|
||||
#include "Tier1/CTimer.h"
|
||||
#include "Tier1/CTask.h"
|
||||
|
||||
extern "C" {
|
||||
#include "Tier0/heap.h"
|
||||
#include "Tier0/panic.h"
|
||||
#include "Tier0/kstdio.h"
|
||||
#include "Tier0/interrupts.h"
|
||||
}
|
||||
|
||||
volatile CScheduler g_Scheduler;
|
||||
u32 CScheduler::m_NumTicks = 0;
|
||||
|
||||
CScheduler::CScheduler(void)
|
||||
{
|
||||
|
@ -31,21 +34,42 @@ CTask *CScheduler::GetCurrentTask(void)
|
|||
return g_Scheduler.m_CurrentScheduler->GetCurrentTask();
|
||||
}
|
||||
|
||||
void CScheduler::PrioritizeTask(CTask *Task)
|
||||
{
|
||||
g_Scheduler.m_CurrentScheduler->PrioritizeTask(Task);
|
||||
}
|
||||
|
||||
void CScheduler::Enable(void)
|
||||
{
|
||||
// 20ms quntum
|
||||
CTimer::Create(200, -1, TimerTick);
|
||||
CTimer::SetFastTimerHook(TimerTick);
|
||||
|
||||
// Add the Yield interrupt
|
||||
interrupts_setup_isr(CSCHEDULER_INTERRUPT_YIELD, (void*)Yield, E_INTERRUPTS_RING0);
|
||||
}
|
||||
|
||||
__attribute__((optimize("O0"))) bool CScheduler::TimerTick(u32 Extra)
|
||||
__attribute__((optimize("O0"))) void CScheduler::Yield(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip)
|
||||
{
|
||||
g_Scheduler.m_CurrentScheduler->NextTask();
|
||||
return true;
|
||||
__asm__ volatile("cli");
|
||||
m_NumTicks = 0;
|
||||
g_Scheduler.m_CurrentScheduler->NextTask(edi, esi, ebp, esp, ebx, edx, ecx, eax, eip);
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
void CScheduler::NextTask(void)
|
||||
__attribute__((optimize("O0"))) void CScheduler::TimerTick(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip)
|
||||
{
|
||||
g_Scheduler.m_CurrentScheduler->NextTask();
|
||||
if (m_NumTicks > 20)
|
||||
{
|
||||
m_NumTicks = 0;
|
||||
g_Scheduler.m_CurrentScheduler->NextTask(edi, esi, ebp, esp, ebx, edx, ecx, eax, eip);
|
||||
}
|
||||
m_NumTicks++;
|
||||
}
|
||||
|
||||
__attribute__((optimize("O0"))) void CScheduler::NextTask(void)
|
||||
{
|
||||
__asm__ volatile("pusha");
|
||||
__asm__ volatile ("int $0x99");
|
||||
__asm__ volatile("popa");
|
||||
}
|
||||
|
||||
void CScheduler::DispatchAvailableSemaphore(CSemaphore *Semaphore)
|
||||
|
|
|
@ -132,9 +132,11 @@ void CTask::Dump(void)
|
|||
m_ESP, m_EBP, m_EIP);
|
||||
}
|
||||
|
||||
void CTask::Yield(void)
|
||||
__attribute__((optimize("O0"))) void CTask::Yield(void)
|
||||
{
|
||||
//kprintf("Entering NextTask\n");
|
||||
CScheduler::NextTask();
|
||||
//kprintf("returned from NextTask\n");
|
||||
}
|
||||
|
||||
void CTask::WaitForSemaphore(T_SEMAPHORE *Semaphore)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "Tier1/CTimer.h"
|
||||
#include "Tier1/CScheduler.h"
|
||||
using namespace cb;
|
||||
|
||||
extern "C" {
|
||||
|
@ -6,9 +7,11 @@ extern "C" {
|
|||
#include "Tier0/interrupts.h"
|
||||
}
|
||||
|
||||
TTimerFastHook CTimer::m_FastHook = 0;
|
||||
volatile u32 CTimer::m_nTicks = 0;
|
||||
bool CTimer::m_bInitialized = false;
|
||||
CLinearList<TCallbackInfo> CTimer::m_Callbacks;
|
||||
CSemaphore CTimer::m_GetTicksSemaphore;
|
||||
|
||||
void CTimer::Initialize(void)
|
||||
{
|
||||
|
@ -23,9 +26,22 @@ void CTimer::Initialize(void)
|
|||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
void CTimer::Dispatch(void *Registers)
|
||||
void CTimer::SetFastTimerHook(TTimerFastHook Hook)
|
||||
{
|
||||
__asm__ volatile("cli");
|
||||
|
||||
m_FastHook = Hook;
|
||||
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
void CTimer::Dispatch(u32 edi, u32 esi, u32 ebp, u32 esp, u32 ebx, u32 edx, u32 ecx, u32 eax, u32 eip)
|
||||
{
|
||||
__asm__ volatile("cli");
|
||||
|
||||
if (m_FastHook)
|
||||
(*m_FastHook)(edi, esi, ebp, esp, ebx, edx, ecx, eax, eip);
|
||||
|
||||
m_nTicks++;
|
||||
|
||||
if (m_nTicks > (0xFFFFFFFF - 1000)) // 1000 ticks margin
|
||||
|
@ -49,8 +65,10 @@ void CTimer::Dispatch(void *Registers)
|
|||
m_Callbacks.Delete(i);
|
||||
// TODO: fix this hack
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
// We can only take care of one timer callback...
|
||||
CScheduler::PrioritizeTask(Callback.Task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -63,6 +81,9 @@ void CTimer::Dispatch(void *Registers)
|
|||
}
|
||||
interrupts_irq_finish(0);
|
||||
__asm__ volatile("sti");
|
||||
|
||||
// Tough love for the current task.
|
||||
//CScheduler::GetCurrentTask()->Yield();
|
||||
}
|
||||
|
||||
void CTimer::Reschedule(void)
|
||||
|
@ -88,8 +109,10 @@ void CTimer::Create(u32 Interval, s32 Times, TTimerCallback Callback, u32 Extra)
|
|||
NewCallback.Interval = Interval;
|
||||
NewCallback.Times = Times;
|
||||
NewCallback.Callback = Callback;
|
||||
NewCallback.NextCall = m_nTicks + Interval;
|
||||
// Why minus 1? "Lag" compensation.
|
||||
NewCallback.NextCall = m_nTicks + Interval - 1;
|
||||
NewCallback.Extra = Extra;
|
||||
NewCallback.Task = CScheduler::GetCurrentTask();
|
||||
|
||||
m_Callbacks.Push(NewCallback);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue