From 07f4f66ba52d23977c58c75bccd0d7f0a813c83e Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Thu, 14 Apr 2011 21:43:46 +0200 Subject: [PATCH] penis --- Makefile | 1 + include/Tier1/CRoundRobinScheduler.h | 21 +++ include/Tier1/CScheduler.h | 7 +- include/Tier1/CTask.h | 20 ++- include/Tier1/IScheduler.h | 16 ++ include/Tier1/Util/CLinearList.h | 225 +++++++++++++++++++++++++++ include/Tier1/Util/CVector.h | 150 +++++++++++++++++- include/types.h | 1 + src/Tier1/CKernel.cpp | 4 + src/Tier1/CRoundRobinScheduler.cpp | 90 +++++++++++ src/Tier1/CScheduler.cpp | 103 +----------- src/Tier1/CTask.cpp | 5 - src/Tier1/Util/CVector.cpp | 125 ++++++++++++++- 13 files changed, 646 insertions(+), 122 deletions(-) create mode 100644 include/Tier1/CRoundRobinScheduler.h create mode 100644 include/Tier1/IScheduler.h create mode 100644 include/Tier1/Util/CLinearList.h create mode 100644 src/Tier1/CRoundRobinScheduler.cpp diff --git a/Makefile b/Makefile index 991704c..3913e84 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/include/Tier1/CRoundRobinScheduler.h b/include/Tier1/CRoundRobinScheduler.h new file mode 100644 index 0000000..c4807d4 --- /dev/null +++ b/include/Tier1/CRoundRobinScheduler.h @@ -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 m_TaskQueue; + u32 m_TaskQueuePosition; + }; +}; + +#endif diff --git a/include/Tier1/CScheduler.h b/include/Tier1/CScheduler.h index 03edd30..1bc9a5a 100644 --- a/include/Tier1/CScheduler.h +++ b/include/Tier1/CScheduler.h @@ -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); }; }; diff --git a/include/Tier1/CTask.h b/include/Tier1/CTask.h index 4431338..7c4f126 100644 --- a/include/Tier1/CTask.h +++ b/include/Tier1/CTask.h @@ -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); diff --git a/include/Tier1/IScheduler.h b/include/Tier1/IScheduler.h new file mode 100644 index 0000000..d437c3e --- /dev/null +++ b/include/Tier1/IScheduler.h @@ -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 diff --git a/include/Tier1/Util/CLinearList.h b/include/Tier1/Util/CLinearList.h new file mode 100644 index 0000000..d05a371 --- /dev/null +++ b/include/Tier1/Util/CLinearList.h @@ -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 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 CLinearList<_T>::CLinearList(void) + { + m_Data = 0; + m_SizeCacheValid = true; + m_SizeCache = 0; + } + + template 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 _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 _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 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 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 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 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 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 diff --git a/include/Tier1/Util/CVector.h b/include/Tier1/Util/CVector.h index eb9c56b..2e39d38 100644 --- a/include/Tier1/Util/CVector.h +++ b/include/Tier1/Util/CVector.h @@ -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 class CVector { + template 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 CVector<_T>::CVector(u32 StartElements) + { + m_MemorySize = StartElements; + m_Size = 0; + + if (m_MemorySize > 0) + m_Members = (_T*)kmalloc(m_MemorySize * sizeof(_T)); + } + + template CVector<_T>::~CVector(void) + { + if (m_MemorySize > 0) + kfree(m_Members); + } + + template _T &CVector<_T>::operator[](u32 Index) + { + ASSERT(Index < m_Size); + return m_Members[Index]; + } + + template const _T &CVector<_T>::operator[](u32 Index) const + { + ASSERT(Index < m_Size); + return m_Members[Index]; + } + + template _T &CVector<_T>::Head(void) + { + ASSERT(m_Size > 0); + return m_Members[Size() - 1]; + } + + template const _T &CVector<_T>::Head(void) const + { + ASSERT(m_Size > 0); + return m_Members[Size() - 1]; + } + + template _T &CVector<_T>::Tail(void) + { + ASSERT(m_Size > 0); + return m_Members[0]; + } + + template const _T &CVector<_T>::Tail(void) const + { + ASSERT(m_Size > 0); + return m_Members[0]; + } + + template _T *CVector<_T>::BaseAddress(void) + { + return m_Members; + } + + template const _T *CVector<_T>::BaseAddress(void) const + { + return m_Members; + } + + template u32 CVector<_T>::Size(void) + { + return m_Size; + } + + template 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 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 _T &CVector<_T>::Pop(void) + { + ASSERT(m_Size > 0); + + } + + template 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 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 void CVector<_T>::PushNew(void) + { + if (m_Size + 1 > m_MemorySize) + MoarMemoryPlox(); + + (m_Members + m_Size) = new _T(); + + m_Size++; + } }; #endif diff --git a/include/types.h b/include/types.h index 16ffb34..f43ad59 100644 --- a/include/types.h +++ b/include/types.h @@ -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; diff --git a/src/Tier1/CKernel.cpp b/src/Tier1/CKernel.cpp index 4a4fda5..accbceb 100644 --- a/src/Tier1/CKernel.cpp +++ b/src/Tier1/CKernel.cpp @@ -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(); diff --git a/src/Tier1/CRoundRobinScheduler.cpp b/src/Tier1/CRoundRobinScheduler.cpp new file mode 100644 index 0000000..dd6273f --- /dev/null +++ b/src/Tier1/CRoundRobinScheduler.cpp @@ -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; +} diff --git a/src/Tier1/CScheduler.cpp b/src/Tier1/CScheduler.cpp index fe10bb6..1944bc4 100644 --- a/src/Tier1/CScheduler.cpp +++ b/src/Tier1/CScheduler.cpp @@ -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(); } diff --git a/src/Tier1/CTask.cpp b/src/Tier1/CTask.cpp index bae23c1..4e45c66 100644 --- a/src/Tier1/CTask.cpp +++ b/src/Tier1/CTask.cpp @@ -131,8 +131,3 @@ void CTask::Dump(void) m_ESP, m_EBP, m_EIP); } -u32 CTask::GetPID(void) -{ - return m_PID; -} - diff --git a/src/Tier1/Util/CVector.cpp b/src/Tier1/Util/CVector.cpp index 9978c5e..0e7d771 100644 --- a/src/Tier1/Util/CVector.cpp +++ b/src/Tier1/Util/CVector.cpp @@ -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 - -tmpl CVector::CVector(u32 StartElements) +template 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 CVector<_T>::~CVector(void) { if (m_MemorySize > 0) - + kfree(m_Members); } + +template _T &CVector<_T>::operator[](u32 Index) +{ + ASSERT(Index < m_Size); + return m_Members[Index]; +} + +template const _T &CVector<_T>::operator[](u32 Index) const +{ + ASSERT(Index < m_Size); + return m_Members[Index]; +} + +template _T &CVector<_T>::Head(void) +{ + ASSERT(m_Size > 0); + return m_Members[Size() - 1]; +} + +template const _T &CVector<_T>::Head(void) const +{ + ASSERT(m_Size > 0); + return m_Members[Size() - 1]; +} + +template _T &CVector<_T>::Tail(void) +{ + ASSERT(m_Size > 0); + return m_Members[0]; +} + +template const _T &CVector<_T>::Tail(void) const +{ + ASSERT(m_Size > 0); + return m_Members[0]; +} + +template _T *CVector<_T>::BaseAddress(void) +{ + return m_Members; +} + +template const _T *CVector<_T>::BaseAddress(void) const +{ + return m_Members; +} + +template u32 CVector<_T>::Size(void) +{ + return m_Size; +} + +template 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 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 _T &CVector<_T>::Pop(void) +{ + ASSERT(m_Size > 0); + +} + +template 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 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 void CVector<_T>::PushNew(void) +{ + if (m_Size + 1 > m_MemorySize) + MoarMemoryPlox(); + + (m_Members + m_Size) = new _T(); + + m_Size++; +}*/