Some scheduler fixes.

alentours-dev
Sergiusz Bazanski 2011-06-27 17:59:54 +02:00
parent 11cf26eb54
commit 164ea30d44
13 changed files with 158 additions and 52 deletions

View File

@ -1,7 +1,7 @@
#Sun May 08 13:56:50 CEST 2011 #Sun May 08 17:23:22 CEST 2011
eclipse.preferences.version=1 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/delimiter=;
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/PATH/operation=replace 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/append=true
environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/appendContributed=true environment/project/cdt.managedbuild.toolchain.gnu.mingw.base.561123667/appendContributed=true

View File

@ -3,7 +3,7 @@
# Seriously. # Seriously.
# #
# Fuck M4. I do this because it's probably the most portable way, and I don't # 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 # 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 # 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 # way. There are better way to do the hthings I do below, but who gives a

View File

@ -9,13 +9,16 @@ namespace cb {
public: public:
void Enable(bool Enabled); void Enable(bool Enabled);
void AddTask(CTask *Task); 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); CTask *GetCurrentTask(void);
void SetSemaphoreAvailable(CSemaphore *Semaphore); void SetSemaphoreAvailable(CSemaphore *Semaphore);
void PrioritizeTask(CTask *Task);
private: private:
CTask *m_CurrentTask; CTask *m_CurrentTask;
CLinearList<CTask *> m_TaskQueue; CLinearList<CTask *> m_TaskQueue;
u32 m_iTaskQueuePosition; u32 m_iTaskQueuePosition;
CTask *m_PrioritizedTask;
}; };
}; };

View File

@ -7,6 +7,8 @@
#include "Tier1/IScheduler.h" #include "Tier1/IScheduler.h"
#include "Tier1/CSemaphore.h" #include "Tier1/CSemaphore.h"
#define CSCHEDULER_INTERRUPT_YIELD 0x99
extern "C" { extern "C" {
#include "Tier0/interrupts.h" #include "Tier0/interrupts.h"
} }
@ -16,17 +18,21 @@ namespace cb {
CTask *Task; CTask *Task;
struct STaskQueueNode *Next; struct STaskQueueNode *Next;
} TTaskQueueNode; } TTaskQueueNode;
class CScheduler { class CScheduler{
private: private:
IScheduler *m_CurrentScheduler; 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: public:
CScheduler(void); CScheduler(void);
static void Enable(void); static void Enable(void);
static void AddTask(CTask *Task); static void AddTask(CTask *Task);
static CTask *GetCurrentTask(void); static CTask *GetCurrentTask(void);
static void NextTask(void); static void NextTask();
static void PrioritizeTask(CTask *Task);
static void DispatchAvailableSemaphore(CSemaphore *Semaphore); static void DispatchAvailableSemaphore(CSemaphore *Semaphore);
}; };

View File

@ -9,7 +9,7 @@ extern "C" {
namespace cb { namespace cb {
class CSemaphore { class CSemaphore {
private: protected:
T_ATOMIC m_Available; T_ATOMIC m_Available;
public: public:
CSemaphore(u32 Available = 1); CSemaphore(u32 Available = 1);

View File

@ -3,34 +3,46 @@
#include "Tier1/CInterruptDispatcher.h" #include "Tier1/CInterruptDispatcher.h"
#include "Tier1/Util/CLinearList.h" #include "Tier1/Util/CLinearList.h"
#include "Tier1/CTask.h"
#include "Tier1/CSemaphore.h"
#include "types.h" #include "types.h"
namespace cb { namespace cb {
typedef bool(*TTimerCallback)(u32); typedef bool(*TTimerCallback)(u32);
typedef void(*TTimerFastHook)(u32, u32, u32, u32, u32, u32, u32, u32, u32);
typedef struct { typedef struct {
TTimerCallback Callback; TTimerCallback Callback;
u32 Interval; u32 Interval;
s32 Times; s32 Times;
u32 NextCall; u32 NextCall;
u32 Extra; u32 Extra;
CTask *Task;
} TCallbackInfo; } TCallbackInfo;
class CTimer { class CTimer {
public: public:
static void Create(u32 Interval, s32 Times, TTimerCallback Callback, static void Create(u32 Interval, s32 Times, TTimerCallback Callback,
u32 Extra = 0); 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) inline static u32 GetTicks(void)
{ {
if (!m_bInitialized) if (!m_bInitialized)
Initialize(); Initialize();
return m_nTicks; m_GetTicksSemaphore.Acquire();
volatile u32 Ticks = m_nTicks;
m_GetTicksSemaphore.Release();
return Ticks;
} }
private: private:
static CLinearList<TCallbackInfo> m_Callbacks; static CLinearList<TCallbackInfo> m_Callbacks;
volatile static u32 m_nTicks; volatile static u32 m_nTicks;
static void Initialize(void); 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 bool m_bInitialized;
static TTimerFastHook m_FastHook;
static CSemaphore m_GetTicksSemaphore;
// Called when the number of ticks is just about to overflow. // Called when the number of ticks is just about to overflow.
// Reschedules all the callbacks. // Reschedules all the callbacks.
static void Reschedule(void); static void Reschedule(void);

View File

@ -9,9 +9,10 @@ namespace cb {
public: public:
virtual void Enable(bool Enabled) = 0; virtual void Enable(bool Enabled) = 0;
virtual void AddTask(CTask *Task) = 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 CTask *GetCurrentTask(void) = 0;
virtual void SetSemaphoreAvailable(CSemaphore *Semaphore) = 0; virtual void SetSemaphoreAvailable(CSemaphore *Semaphore) = 0;
virtual void PrioritizeTask(CTask *Task) = 0;
}; };
}; };

View File

@ -5,6 +5,7 @@ extern "C" {
#include "Tier0/heap.h" #include "Tier0/heap.h"
#include "Tier0/panic.h" #include "Tier0/panic.h"
#include "Tier0/kstdlib.h" #include "Tier0/kstdlib.h"
#include "Tier0/kstdio.h"
}; };
namespace cb { namespace cb {
@ -96,12 +97,18 @@ namespace cb {
template <class _T> _T &CLinearList<_T>::operator[](u32 Index) template <class _T> _T &CLinearList<_T>::operator[](u32 Index)
{ {
ASSERT(m_Data != 0); ASSERT(m_Data != 0);
TLinearListNode *Node = m_Data; TLinearListNode *Node = m_Data;
for (u32 i = 0; i < Index; i++) for (u32 i = 0; i < Index; i++)
{ {
Node = Node->Next; Node = Node->Next;
ASSERT(Node != 0); //ASSERT(Node != 0);
if (Node == 0)
{
kprintf("fail\n");
__asm__ volatile("cli");
for(;;){}
}
} }
return Node->Data; return Node->Data;
@ -164,10 +171,25 @@ namespace cb {
m_SizeCacheValid = false; m_SizeCacheValid = false;
return; return;
} }
ASSERT(m_Data != 0); 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; TLinearListNode *NodeBefore = m_Data;
for (u32 i = 0; i < Index - 1; i++) for (s32 i = 0; i < (s32)Index - 1; i++)
{ {
NodeBefore = NodeBefore->Next; NodeBefore = NodeBefore->Next;
ASSERT(NodeBefore != 0); ASSERT(NodeBefore != 0);

View File

@ -66,8 +66,12 @@ void CKernel::Start(void)
else else
{ {
for (;;) { for (;;) {
CScheduler::GetCurrentTask()->Sleep(1000); //CScheduler::GetCurrentTask()->Sleep(1000);
kprintf("[i] Hello! I'm the child process.\n"); 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());
} }
} }
} }

View File

@ -10,30 +10,43 @@ extern "C" {
void CRoundRobinScheduler::Enable(bool Enabled) void CRoundRobinScheduler::Enable(bool Enabled)
{ {
m_iTaskQueuePosition = 0; 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!"); PANIC("No tasks in queue!");
// Fetch next task. // Fetch next task.
CTask *NextTask; CTask *NextTask;
do { /*if (m_PrioritizedTask != 0)
m_iTaskQueuePosition++; {
NextTask = m_PrioritizedTask;
if (m_iTaskQueuePosition >= m_TaskQueue.GetSize()) m_PrioritizedTask = 0;
// Something happened - restart the queue
m_iTaskQueuePosition = 0;
NextTask = m_TaskQueue[m_iTaskQueuePosition];
} }
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()) if (m_CurrentTask->GetPID() == NextTask->GetPID())
return; 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); //kprintf("[i] %i -> %i (%x)\n", m_CurrentTask->GetPID(), NextTask->GetPID(), NextTask);
// Read task details // Read task details
@ -47,26 +60,18 @@ __attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
} }
// Save current task details // Save current task details
__asm__ volatile("mov %%esp, %0" : "=r"(ESP)); m_CurrentTask->SetEBP(ebp);
__asm__ volatile("mov %%ebp, %0" : "=r"(EBP)); m_CurrentTask->SetESP(esp);
m_CurrentTask->SetEBP(EBP);
m_CurrentTask->SetESP(ESP);
// Return point // Return point
volatile u32 ReturnPoint = ctask_geteip(); volatile u32 ReturnPoint = eip;
if (ReturnPoint == 0xFEEDFACE)
{
//We are in the next task already
return;
}
m_CurrentTask->SetEIP(ReturnPoint); m_CurrentTask->SetEIP(ReturnPoint);
// Switch to next task // Switch to next task
m_CurrentTask = NextTask; m_CurrentTask = NextTask;
Directory = NextTask->GetPageDirectoryPhysicalAddress(); 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); // NewEBP, Directory);
//for(;;){} //for(;;){}
interrupts_irq_finish(0); interrupts_irq_finish(0);
@ -75,7 +80,6 @@ __attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
"movl %2, %%ebp\n" "movl %2, %%ebp\n"
"movl %3, %%cr3\n" "movl %3, %%cr3\n"
"movl %0, %%ecx\n" "movl %0, %%ecx\n"
"movl $0xFEEDFACE, %%eax\n"
"jmp *%%ecx" :: "jmp *%%ecx" ::
"r"(NewEIP), "r"(NewEIP),
"r"(NewESP), "r"(NewESP),
@ -95,6 +99,11 @@ CTask *CRoundRobinScheduler::GetCurrentTask(void)
return m_CurrentTask; return m_CurrentTask;
} }
void CRoundRobinScheduler::PrioritizeTask(CTask *Task)
{
m_PrioritizedTask = Task;
}
void CRoundRobinScheduler::SetSemaphoreAvailable(CSemaphore *Semaphore) void CRoundRobinScheduler::SetSemaphoreAvailable(CSemaphore *Semaphore)
{ {
u32 Physical = GetCurrentTask()->GetPageDirectory()-> u32 Physical = GetCurrentTask()->GetPageDirectory()->

View File

@ -3,14 +3,17 @@ using namespace cb;
#include "Tier1/CRoundRobinScheduler.h" #include "Tier1/CRoundRobinScheduler.h"
#include "Tier1/CTimer.h" #include "Tier1/CTimer.h"
#include "Tier1/CTask.h"
extern "C" { extern "C" {
#include "Tier0/heap.h" #include "Tier0/heap.h"
#include "Tier0/panic.h" #include "Tier0/panic.h"
#include "Tier0/kstdio.h" #include "Tier0/kstdio.h"
#include "Tier0/interrupts.h"
} }
volatile CScheduler g_Scheduler; volatile CScheduler g_Scheduler;
u32 CScheduler::m_NumTicks = 0;
CScheduler::CScheduler(void) CScheduler::CScheduler(void)
{ {
@ -31,21 +34,42 @@ CTask *CScheduler::GetCurrentTask(void)
return g_Scheduler.m_CurrentScheduler->GetCurrentTask(); return g_Scheduler.m_CurrentScheduler->GetCurrentTask();
} }
void CScheduler::PrioritizeTask(CTask *Task)
{
g_Scheduler.m_CurrentScheduler->PrioritizeTask(Task);
}
void CScheduler::Enable(void) void CScheduler::Enable(void)
{ {
// 20ms quntum CTimer::SetFastTimerHook(TimerTick);
CTimer::Create(200, -1, 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(); __asm__ volatile("cli");
return true; 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) void CScheduler::DispatchAvailableSemaphore(CSemaphore *Semaphore)

View File

@ -132,9 +132,11 @@ void CTask::Dump(void)
m_ESP, m_EBP, m_EIP); m_ESP, m_EBP, m_EIP);
} }
void CTask::Yield(void) __attribute__((optimize("O0"))) void CTask::Yield(void)
{ {
//kprintf("Entering NextTask\n");
CScheduler::NextTask(); CScheduler::NextTask();
//kprintf("returned from NextTask\n");
} }
void CTask::WaitForSemaphore(T_SEMAPHORE *Semaphore) void CTask::WaitForSemaphore(T_SEMAPHORE *Semaphore)

View File

@ -1,4 +1,5 @@
#include "Tier1/CTimer.h" #include "Tier1/CTimer.h"
#include "Tier1/CScheduler.h"
using namespace cb; using namespace cb;
extern "C" { extern "C" {
@ -6,9 +7,11 @@ extern "C" {
#include "Tier0/interrupts.h" #include "Tier0/interrupts.h"
} }
TTimerFastHook CTimer::m_FastHook = 0;
volatile u32 CTimer::m_nTicks = 0; volatile u32 CTimer::m_nTicks = 0;
bool CTimer::m_bInitialized = false; bool CTimer::m_bInitialized = false;
CLinearList<TCallbackInfo> CTimer::m_Callbacks; CLinearList<TCallbackInfo> CTimer::m_Callbacks;
CSemaphore CTimer::m_GetTicksSemaphore;
void CTimer::Initialize(void) void CTimer::Initialize(void)
{ {
@ -23,9 +26,22 @@ void CTimer::Initialize(void)
m_bInitialized = true; 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"); __asm__ volatile("cli");
if (m_FastHook)
(*m_FastHook)(edi, esi, ebp, esp, ebx, edx, ecx, eax, eip);
m_nTicks++; m_nTicks++;
if (m_nTicks > (0xFFFFFFFF - 1000)) // 1000 ticks margin if (m_nTicks > (0xFFFFFFFF - 1000)) // 1000 ticks margin
@ -49,8 +65,10 @@ void CTimer::Dispatch(void *Registers)
m_Callbacks.Delete(i); m_Callbacks.Delete(i);
// TODO: fix this hack // TODO: fix this hack
i--; i--;
continue;
} }
// We can only take care of one timer callback...
CScheduler::PrioritizeTask(Callback.Task);
break;
} }
} }
else else
@ -63,6 +81,9 @@ void CTimer::Dispatch(void *Registers)
} }
interrupts_irq_finish(0); interrupts_irq_finish(0);
__asm__ volatile("sti"); __asm__ volatile("sti");
// Tough love for the current task.
//CScheduler::GetCurrentTask()->Yield();
} }
void CTimer::Reschedule(void) void CTimer::Reschedule(void)
@ -88,8 +109,10 @@ void CTimer::Create(u32 Interval, s32 Times, TTimerCallback Callback, u32 Extra)
NewCallback.Interval = Interval; NewCallback.Interval = Interval;
NewCallback.Times = Times; NewCallback.Times = Times;
NewCallback.Callback = Callback; NewCallback.Callback = Callback;
NewCallback.NextCall = m_nTicks + Interval; // Why minus 1? "Lag" compensation.
NewCallback.NextCall = m_nTicks + Interval - 1;
NewCallback.Extra = Extra; NewCallback.Extra = Extra;
NewCallback.Task = CScheduler::GetCurrentTask();
m_Callbacks.Push(NewCallback); m_Callbacks.Push(NewCallback);
} }