alentours-dev
Sergiusz Bazanski 2011-04-14 21:43:46 +02:00
parent b1892a7e82
commit 07f4f66ba5
13 changed files with 646 additions and 122 deletions

View File

@ -43,6 +43,7 @@ obj/src/%.o : src/%.c
obj/src/%.xo : src/%.cpp
@echo "[i] Compiling $*.cpp ..."
@if [ -e obj/src/$*.xo ] ; then rm obj/src/$*.xo ; fi
@mkdir -p obj/src/$*.xo
@rmdir obj/src/$*.xo
@$(CX) $(CXFLAGS) -c src/$*.cpp -o obj/src/$*.xo

View File

@ -0,0 +1,21 @@
#ifndef __CROUNDROBINSCHEDULER_H__
#define __CROUNDROBINSCHEDULER_H__
#include "Tier1/IScheduler.h"
#include "Tier1/Util/CLinearList.h"
namespace cb {
class CRoundRobinScheduler : public IScheduler {
public:
void Enable(bool Enabled);
void AddTask(CTask *Task);
void NextTask(void);
CTask *GetCurrentTask(void);
private:
CTask *m_CurrentTask;
CLinearList<CTask *> m_TaskQueue;
u32 m_TaskQueuePosition;
};
};
#endif

View File

@ -4,6 +4,7 @@
#include "types.h"
#include "Tier1/CTask.h"
#include "Tier1/IScheduler.h"
extern "C" {
#include "Tier0/interrupts.h"
@ -16,17 +17,13 @@ namespace cb {
} TTaskQueueNode;
class CScheduler {
private:
CTask *m_CurrentTask;
TTaskQueueNode *m_TaskQueueStart;
TTaskQueueNode *m_TaskQueueCurrent;
IScheduler *m_CurrentScheduler;
static void TimerTick(T_ISR_REGISTERS R);
public:
CScheduler(void);
static void Enable(void);
static void AddTask(CTask *Task);
static void NextTask(void);
static CTask *GetCurrentTask(void);
};
};

View File

@ -129,7 +129,25 @@ namespace cb {
// Equivalent of the POSIX fork() call.
CTask *Fork(void);
u32 GetPID(void);
inline u32 GetPID(void) { return m_PID; }
inline u32 GetESP(void) { return m_ESP; }
inline u32 GetEIP(void) { return m_EIP; }
inline u32 GetEBP(void) { return m_EBP; }
inline u32 GetPageDirectoryPhysicalAddress(void)
{
//return m_Directory->m_Directory->PhysicalAddress;
return 0;
}
inline void SetESP(u32 ESP) { m_ESP = ESP; }
inline void SetEIP(u32 EIP) { m_EIP = EIP; }
inline void SetEBP(u32 EBP) { m_EBP = EBP; }
inline void SetPageDirectory(CPageDirectory *Directory)
{
m_Directory = Directory;
}
void Dump(void);

View File

@ -0,0 +1,16 @@
#ifndef __ISCHEDULER_H__
#define __ISCHEDULER_H__
#include "Tier1/CTask.h"
namespace cb {
class IScheduler {
public:
virtual void Enable(bool Enabled) = 0;
virtual void AddTask(CTask *Task) = 0;
virtual void NextTask(void) = 0;
virtual CTask *GetCurrentTask(void) = 0;
};
};
#endif

View File

@ -0,0 +1,225 @@
#ifndef __CLINEAR_LIST_H__
#define __CLINEAR_LIST_H__
extern "C" {
#include "Tier0/heap.h"
#include "Tier0/panic.h"
};
namespace cb {
template <class _T> class CLinearList {
public:
CLinearList(void);
// Stack-like access
void Push(const _T &Element);
_T &Pop(void);
// Indexing operator
_T &operator[](u32 Index);
const _T &operator[](u32 Index) const;
void Insert(const _T &Element, u32 Index = 0);
void Delete(u32 Index);
u32 GetSize(void) const;
u32 GetSize(void);
private:
struct SLinearListNode {
_T Data;
struct SLinearListNode *Next;
};
typedef struct SLinearListNode TLinearListNode;
TLinearListNode *m_Data;
bool m_SizeCacheValid;
u32 m_SizeCache;
};
template <class _T> CLinearList<_T>::CLinearList(void)
{
m_Data = 0;
m_SizeCacheValid = true;
m_SizeCache = 0;
}
template <class _T> void CLinearList<_T>::Push(const _T &Element)
{
if (m_Data == 0)
{
m_Data = (TLinearListNode *)kmalloc(sizeof(TLinearListNode));
m_Data->Data = Element;
m_Data->Next = 0;
m_SizeCacheValid = false;
return;
}
TLinearListNode *LastNode = m_Data;
while (LastNode->Next != 0)
LastNode = LastNode->Next;
TLinearListNode *NewNode =
(TLinearListNode *)kmalloc(sizeof(TLinearListNode));
NewNode->Data = Element;
NewNode->Next = 0;
LastNode->Next = NewNode;
m_SizeCacheValid = false;
return;
}
template <class _T> _T &CLinearList<_T>::Pop(void)
{
ASSERT(m_Data != 0);
if (m_Data->Next == 0)
{
_T &Element = m_Data->Data;
kfree((void*)m_Data);
m_Data = 0;
m_SizeCacheValid = false;
return Element;
}
TLinearListNode *LastNode = m_Data;
while (LastNode->Next->Next != 0)
LastNode = LastNode ->Next;
_T &Element = LastNode->Next->Data;
kfree((void*)LastNode->Next);
LastNode->Next = 0;
m_SizeCacheValid = false;
return Element;
}
template <class _T> _T &CLinearList<_T>::operator[](u32 Index)
{
ASSERT(m_Data != 0);
TLinearListNode *Node = m_Data;
for (u32 i = 0; i < Index; i++)
{
Node = Node->Next;
ASSERT(Node != 0);
}
return Node->Data;
}
template <class _T> const _T &CLinearList<_T>::operator[](u32 Index) const
{
ASSERT(m_Data != 0);
TLinearListNode *Node = m_Data;
for (u32 i = 0; i < Index; i++)
{
Node = Node->Next;
ASSERT(Node);
}
return Node->Data;
}
template <class _T> void CLinearList<_T>::Insert(
const _T &Element, u32 Index)
{
if (m_Data == 0 && Index == 0)
{
Push(Element);
m_SizeCacheValid = false;
return;
}
ASSERT(m_Data);
TLinearListNode *NodeBefore;
for (u32 i = 0; i < Index - 1; i++)
{
NodeBefore = NodeBefore->Next;
ASSERT(NodeBefore);
}
// Last node?
if (NodeBefore->Next == 0)
{
Push(Element);
return;
}
TLinearListNode *NodeAfter = NodeBefore->Next;
TLinearListNode *NewNode = (TLinearListNode*)
kmalloc(sizeof(TLinearListNode));
NewNode->Data = Element;
NewNode->Next = NodeAfter;
NodeBefore->Next = NewNode;
m_SizeCacheValid = false;
}
template <class _T> void CLinearList<_T>::Delete(u32 Index)
{
if (m_Data == 0 && Index == 0)
{
Pop();
m_SizeCacheValid = false;
return;
}
ASSERT(m_Data);
TLinearListNode *NodeBefore = m_Data;
for (u32 i = 0; i < Index - 1; i++)
{
NodeBefore = NodeBefore->Next;
ASSERT(NodeBefore);
}
TLinearListNode *NodeToBeDeleted = NodeBefore->Next;
ASSERT(NodeToBeDeleted);
TLinearListNode *NodeAfter = NodeToBeDeleted->Next;
kfree((void*)NodeToBeDeleted);
NodeBefore->Next = NodeAfter;
m_SizeCacheValid = false;
}
template <class _T> u32 CLinearList<_T>::GetSize(void) const
{
if (m_SizeCacheValid)
return m_SizeCache;
TLinearListNode *Node = m_Data;
u32 Size = 1;
while (Node->Next != 0)
{
Node = Node->Next;
Size++;
}
return m_SizeCache;
}
template <class _T> u32 CLinearList<_T>::GetSize(void)
{
if (m_SizeCacheValid)
return m_SizeCache;
if (m_Data == 0)
{
m_SizeCache = 0;
m_SizeCacheValid = true;
return 0;
}
u32 Size = 1;
TLinearListNode *Node = m_Data;
while (Node->Next != 0)
{
Node = Node->Next;
Size++;
}
m_SizeCache = Size;
m_SizeCacheValid = true;
return m_SizeCache;
}
};
#endif

View File

@ -1,9 +1,19 @@
#ifndef __CVECTOR_H__
#define __CVECTOR_H__
class cb {
#include "types.h"
extern "C" {
#include "Tier0/heap.h"
#include "Tier0/panic.h"
#include "Tier0/kstdlib.h"
};
#define CVECTOR_MEMCPY_ELEMENTS
namespace cb {
// An STL-like vector implementation for internal use in the kernel
template <typename _T> class CVector {
template <class _T> class CVector {
public:
CVector(u32 StartElements = 32);
~CVector(void);
@ -24,23 +34,147 @@ class cb {
u32 Size(void);
// Search
u32 Find(const _T &Element) const;
s32 Find(const _T &Element) const;
bool HasElement(const _T &Element) const;
// Stack-like properties
void Push(const _T &Element);
void PushNew(void);
_T &Pop(void);
// Used for iteration... I could use another class unstead of u32's,
// but who cares :V
u32 IterationStart(void);
u32 IterationEnd(void);
protected:
_T *m_Members;
u32 m_Size;
u32 m_MemorySize;
// Pretty self-descriptive
void MoarMemoryPlox(void);
};
template <class _T> CVector<_T>::CVector(u32 StartElements)
{
m_MemorySize = StartElements;
m_Size = 0;
if (m_MemorySize > 0)
m_Members = (_T*)kmalloc(m_MemorySize * sizeof(_T));
}
template <class _T> CVector<_T>::~CVector(void)
{
if (m_MemorySize > 0)
kfree(m_Members);
}
template <class _T> _T &CVector<_T>::operator[](u32 Index)
{
ASSERT(Index < m_Size);
return m_Members[Index];
}
template <class _T> const _T &CVector<_T>::operator[](u32 Index) const
{
ASSERT(Index < m_Size);
return m_Members[Index];
}
template <class _T> _T &CVector<_T>::Head(void)
{
ASSERT(m_Size > 0);
return m_Members[Size() - 1];
}
template <class _T> const _T &CVector<_T>::Head(void) const
{
ASSERT(m_Size > 0);
return m_Members[Size() - 1];
}
template <class _T> _T &CVector<_T>::Tail(void)
{
ASSERT(m_Size > 0);
return m_Members[0];
}
template <class _T> const _T &CVector<_T>::Tail(void) const
{
ASSERT(m_Size > 0);
return m_Members[0];
}
template <class _T> _T *CVector<_T>::BaseAddress(void)
{
return m_Members;
}
template <class _T> const _T *CVector<_T>::BaseAddress(void) const
{
return m_Members;
}
template <class _T> u32 CVector<_T>::Size(void)
{
return m_Size;
}
template <class _T> s32 CVector<_T>::Find(const _T &Element) const
{
for (u32 i = 0; i < Size(); i++)
if (m_Members[i] == Element)
return i;
return -1;
}
template <class _T> bool CVector<_T>::HasElement(const _T &Element) const
{
for (u32 i = 0; i < Size(); i++)
if (m_Members[i] == Element)
return true;
return false;
}
template <class _T> _T &CVector<_T>::Pop(void)
{
ASSERT(m_Size > 0);
}
template <class _T> void CVector<_T>::MoarMemoryPlox(void)
{
u32 NewSize = m_MemorySize * 2;
_T *NewData = (_T*)kmalloc(NewSize * sizeof(_T));
// Copy the data over
kmemcpy((void*)NewData, (void*)m_Members, m_MemorySize * sizeof(_T));
kfree(m_Members);
m_Members = NewData;
m_MemorySize = NewSize;
}
template <class _T> void CVector<_T>::Push(const _T &Element)
{
if (m_Size + 1 > m_MemorySize)
MoarMemoryPlox();
#ifdef CVECTOR_MEMCPY_ELEMENTS
kmemcpy((void*)(m_Members + m_Size), (void*)&Element, sizeof(_T));
#else
m_Members[m_Size] = Element;
#endif
m_Size++;
}
template <class _T> void CVector<_T>::PushNew(void)
{
if (m_Size + 1 > m_MemorySize)
MoarMemoryPlox();
(m_Members + m_Size) = new _T();
m_Size++;
}
};
#endif

View File

@ -3,6 +3,7 @@
#ifndef __TYPES_H__
#define __TYPES_H__
typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

View File

@ -5,6 +5,8 @@
#include "Tier1/CPageDirectory.h"
#include "Tier1/CTask.h"
#include "Tier1/CScheduler.h"
#include "Tier1/Util/CVector.h"
#include "Tier1/Util/CLinearList.h"
using namespace cb;
CKernel g_Kernel;
@ -55,6 +57,8 @@ void CKernel::Start(void)
CScheduler::AddTask(KernelTask);
CScheduler::Enable();
//PANIC("I LIKE THE COCK");
CTask *ParentTask = CScheduler::GetCurrentTask();
CTask *NewTask = ParentTask->Fork();

View File

@ -0,0 +1,90 @@
#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_TaskQueuePosition = 0;
}
__attribute__((optimize("O0"))) void CRoundRobinScheduler::NextTask(void)
{
__asm__ volatile("cli");
volatile u32 NewEBP, NewESP, NewEIP, EBP, ESP, Directory;
if (m_TaskQueue.GetSize() == 0)
PANIC("No tasks in queue!");
// Fetch next task.
m_TaskQueuePosition++;
if (m_TaskQueuePosition >= m_TaskQueue.GetSize())
// Something happened - restart the queue
m_TaskQueuePosition = 0;
CTask *NextTask = m_TaskQueue[m_TaskQueuePosition];
// Read task details
NewEBP = NextTask->GetEBP();
NewESP = NextTask->GetESP();
NewEIP = NextTask->GetEIP();
if (!NewEIP || !NewESP || !NewEBP)
{
kprintf("[i] no wai\n");
return;
}
// 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);
// Return point
volatile u32 ReturnPoint = ctask_geteip();
//kprintf("return point %x\n", ReturnPoint);
if (ReturnPoint == 0xFEEDFACE)
{
//We are in the next task already
return;
}
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"
"movl $0xFEEDFACE, %%eax\n"
"jmp *%%ecx" ::
"r"(NewEIP),
"r"(NewESP),
"r"(NewEBP),
"r"(Directory));
}
void CRoundRobinScheduler::AddTask(CTask *Task)
{
__asm__ volatile("cli");
m_TaskQueue.Push(Task);
__asm__ volatile("sti");
}
CTask *CRoundRobinScheduler::GetCurrentTask(void)
{
return m_CurrentTask;
}

View File

@ -1,6 +1,8 @@
#include "Tier1/CScheduler.h"
using namespace cb;
#include "Tier1/CRoundRobinScheduler.h"
extern "C" {
#include "Tier0/heap.h"
#include "Tier0/panic.h"
@ -11,111 +13,20 @@ CScheduler g_Scheduler;
CScheduler::CScheduler(void)
{
m_CurrentTask = 0;
m_TaskQueueStart = 0;
m_TaskQueueCurrent = 0;
m_CurrentScheduler = new CRoundRobinScheduler();
m_CurrentScheduler->Enable(true);
}
void CScheduler::AddTask(CTask *Task)
{
__asm__ volatile("cli");
TTaskQueueNode *Current = g_Scheduler.m_TaskQueueStart;
if (Current == 0)
{
g_Scheduler.m_TaskQueueCurrent = (TTaskQueueNode*)
kmalloc(sizeof(TTaskQueueNode));
g_Scheduler.m_TaskQueueCurrent->Task = Task;
g_Scheduler.m_TaskQueueCurrent->Next = 0;
g_Scheduler.m_TaskQueueStart = g_Scheduler.m_TaskQueueCurrent;
g_Scheduler.m_CurrentTask = Task;
return;
}
while (Current->Next != 0)
Current = Current->Next;
// We are now at the last node.
Current->Next = (TTaskQueueNode*)kmalloc(sizeof(TTaskQueueNode));
Current->Next->Task = Task;
Current->Next->Next = 0;
g_Scheduler.m_CurrentScheduler->AddTask(Task);
__asm__ volatile("sti");
}
#pragma GCC optimize ("O0")
__attribute__((optimize("O0"))) void CScheduler::NextTask(void)
{
__asm__ volatile("cli");
volatile u32 NewEBP, NewESP, NewEIP, EBP, ESP, Directory;
TTaskQueueNode *Next;
/*if (g_Scheduler.m_TaskQueueStart == 0)
PANIC("No tasks in queue!");
if (g_Scheduler.m_TaskQueueCurrent == 0)
PANIC("Current task is null!");*/
// Fetch next task.
if (g_Scheduler.m_TaskQueueCurrent->Next == 0)
Next = g_Scheduler.m_TaskQueueStart;
else
Next = g_Scheduler.m_TaskQueueCurrent->Next;
// Read task details
NewEBP = Next->Task->m_EBP;
NewESP = Next->Task->m_ESP;
NewEIP = Next->Task->m_EIP;
if (!NewEIP || !NewESP || !NewEBP)
{
kprintf("[i] no wai\n");
return;
}
// Save current task details
__asm__ volatile("mov %%esp, %0" : "=r"(ESP));
__asm__ volatile("mov %%ebp, %0" : "=r"(EBP));
g_Scheduler.m_CurrentTask->m_EBP = EBP;
g_Scheduler.m_CurrentTask->m_ESP = ESP;
// Return point
volatile u32 ReturnPoint = ctask_geteip();
//kprintf("return point %x\n", ReturnPoint);
if (ReturnPoint == 0xFEEDFACE)
{
//We are in the next task already
return;
}
g_Scheduler.m_CurrentTask->m_EIP = ReturnPoint;
// Switch to next task
g_Scheduler.m_TaskQueueCurrent = Next;
g_Scheduler.m_CurrentTask = Next->Task;
Directory = Next->Task->m_Directory->m_Directory->PhysicalAddress;
//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"
"movl $0xFEEDFACE, %%eax\n"
"jmp *%%ecx" ::
"r"(NewEIP),
"r"(NewESP),
"r"(NewEBP),
"r"(Directory));
}
CTask *CScheduler::GetCurrentTask(void)
{
return g_Scheduler.m_CurrentTask;
return g_Scheduler.m_CurrentScheduler->GetCurrentTask();
}
void CScheduler::Enable(void)
@ -132,5 +43,5 @@ void CScheduler::Enable(void)
void CScheduler::TimerTick(T_ISR_REGISTERS R)
{
NextTask();
g_Scheduler.m_CurrentScheduler->NextTask();
}

View File

@ -131,8 +131,3 @@ void CTask::Dump(void)
m_ESP, m_EBP, m_EIP);
}
u32 CTask::GetPID(void)
{
return m_PID;
}

View File

@ -1,22 +1,133 @@
#include "Tier1/Utils/CVector.h"
/*#include "Tier1/Util/CVector.h"
using namespace cb;
extern "C" {
#include "Tier0/heap.h"
#include "Tier0/panic.h"
#include "Tier0/kstdlib.h"
};
#define tmpl template <typename _T>
tmpl CVector::CVector(u32 StartElements)
template <class _T> CVector<_T>::CVector(u32 StartElements)
{
m_Size = m_MemorySize = StartElements;
if (m_Size > 0)
m_Members = (_T*)malloc(m_Size * sizeof(_T));
m_Members = (_T*)kmalloc(m_Size * sizeof(_T));
}
tmpl CVector::~CVector(void)
template <class _T> CVector<_T>::~CVector(void)
{
if (m_MemorySize > 0)
kfree(m_Members);
}
template <class _T> _T &CVector<_T>::operator[](u32 Index)
{
ASSERT(Index < m_Size);
return m_Members[Index];
}
template <class _T> const _T &CVector<_T>::operator[](u32 Index) const
{
ASSERT(Index < m_Size);
return m_Members[Index];
}
template <class _T> _T &CVector<_T>::Head(void)
{
ASSERT(m_Size > 0);
return m_Members[Size() - 1];
}
template <class _T> const _T &CVector<_T>::Head(void) const
{
ASSERT(m_Size > 0);
return m_Members[Size() - 1];
}
template <class _T> _T &CVector<_T>::Tail(void)
{
ASSERT(m_Size > 0);
return m_Members[0];
}
template <class _T> const _T &CVector<_T>::Tail(void) const
{
ASSERT(m_Size > 0);
return m_Members[0];
}
template <class _T> _T *CVector<_T>::BaseAddress(void)
{
return m_Members;
}
template <class _T> const _T *CVector<_T>::BaseAddress(void) const
{
return m_Members;
}
template <class _T> u32 CVector<_T>::Size(void)
{
return m_Size;
}
template <class _T> s32 CVector<_T>::Find(const _T &Element) const
{
for (u32 i = 0; i < Size(); i++)
if (m_Members[i] == Element)
return i;
return -1;
}
template <class _T> bool CVector<_T>::HasElement(const _T &Element) const
{
for (u32 i = 0; i < Size(); i++)
if (m_Members[i] == Element)
return true;
return false;
}
template <class _T> _T &CVector<_T>::Pop(void)
{
ASSERT(m_Size > 0);
}
template <class _T> void CVector<_T>::MoarMemoryPlox(void)
{
u32 NewSize = m_MemorySize * 2;
_T *NewData = (_T*)kmalloc(NewSize * sizeof(_T));
// Copy the data over
kmemcpy((void*)NewData, (void*)m_Members, m_MemorySize * sizeof(_T));
kfree(m_Members);
m_Members = NewData;
m_MemorySize = NewSize;
}
template <class _T> void CVector<_T>::Push(const _T &Element)
{
if (m_Size + 1 > m_MemorySize)
MoarMemoryPlox();
#ifdef CVECTOR_MEMCPY_ELEMENTS
kmemcpy((void*)(m_Members + m_Size), (void*)&Element, sizeof(_T));
#else
m_Members[m_Size] = Element;
#endif
m_Size++;
}
template <class _T> void CVector<_T>::PushNew(void)
{
if (m_Size + 1 > m_MemorySize)
MoarMemoryPlox();
(m_Members + m_Size) = new _T();
m_Size++;
}*/