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
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

View File

@ -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

View File

@ -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;
};
};

View File

@ -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);
};

View File

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

View File

@ -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);

View File

@ -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;
};
};

View File

@ -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);

View File

@ -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());
}
}
}

View File

@ -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()->

View File

@ -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)

View File

@ -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)

View File

@ -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);
}