This commit is contained in:
Alex 2023-02-27 22:20:02 +02:00
parent 392ebc9be2
commit 65dfa325e9
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
5 changed files with 221 additions and 145 deletions

View File

@ -27,7 +27,7 @@ volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0}; static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(long id) { return &CPUs[id]; } SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; }
SafeFunction CPUData *GetCurrentCPU() SafeFunction CPUData *GetCurrentCPU()
{ {

View File

@ -124,14 +124,14 @@ namespace Interrupts
if (likely(CoreData != nullptr)) if (likely(CoreData != nullptr))
Core = CoreData->ID; Core = CoreData->ID;
// If this is false, we have a big problem. /* If this is false, we have a big problem. */
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0)) if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0))
{ {
if (Frame->InterruptNumber == CPU::x86::IRQ29) // Halt core interrupt /* Halt core interrupt */
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
CPU::Stop(); CPU::Stop();
Handler *handler = nullptr; Handler *handler = nullptr;
foreach (auto var in RegisteredEvents) foreach (auto var in RegisteredEvents)
{ {
if (var.ID == static_cast<int>(Frame->InterruptNumber)) if (var.ID == static_cast<int>(Frame->InterruptNumber))

View File

@ -90,10 +90,10 @@ NewLock(SchedulerLock);
#define wut_schedbg(m, ...) #define wut_schedbg(m, ...)
#endif #endif
extern "C" SafeFunction __no_instrument_function void TaskingScheduler_OneShot(int TimeSlice) extern "C" SafeFunction NIF void TaskingScheduler_OneShot(int TimeSlice)
{ {
if (TimeSlice == 0) if (TimeSlice == 0)
TimeSlice = 10; TimeSlice = Tasking::TaskPriority::Normal;
#if defined(__amd64__) #if defined(__amd64__)
((APIC::Timer *)Interrupts::apicTimer[GetCurrentCPU()->ID])->OneShot(CPU::x86::IRQ16, TimeSlice); ((APIC::Timer *)Interrupts::apicTimer[GetCurrentCPU()->ID])->OneShot(CPU::x86::IRQ16, TimeSlice);
#elif defined(__i386__) #elif defined(__i386__)
@ -104,47 +104,51 @@ extern "C" SafeFunction __no_instrument_function void TaskingScheduler_OneShot(i
namespace Tasking namespace Tasking
{ {
#if defined(__amd64__) #if defined(__amd64__)
SafeFunction __no_instrument_function bool Task::FindNewProcess(void *CPUDataPointer) SafeFunction NIF bool Task::FindNewProcess(void *CPUDataPointer)
{ {
CPUData *CurrentCPU = (CPUData *)CPUDataPointer; CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
fnp_schedbg("%d processes", ListProcess.size()); fnp_schedbg("%d processes", ListProcess.size());
#ifdef DEBUG_FIND_NEW_PROCESS #ifdef DEBUG_FIND_NEW_PROCESS
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
fnp_schedbg("Process %d %s", pcb->ID, pcb->Name); fnp_schedbg("Process %d %s", process->ID, process->Name);
#endif #endif
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(process))
continue; continue;
switch (pcb->Status) switch (process->Status)
{ {
case TaskStatus::Ready: case TaskStatus::Ready:
fnp_schedbg("Ready process (%s)%d", pcb->Name, pcb->ID); fnp_schedbg("Ready process (%s)%d",
process->Name, process->ID);
break; break;
default: default:
fnp_schedbg("Process \"%s\"(%d) status %d", pcb->Name, pcb->ID, pcb->Status); fnp_schedbg("Process \"%s\"(%d) status %d",
process->Name, process->ID,
process->Status);
/* We don't actually remove the process. RemoveProcess /* We don't actually remove the process. RemoveProcess
firstly checks if it's terminated, if not, it will firstly checks if it's terminated, if not, it will
loop through Threads and call RemoveThread on loop through Threads and call RemoveThread on
terminated threads. */ terminated threads. */
RemoveProcess(pcb); RemoveProcess(process);
continue; continue;
} }
foreach (auto tcb in pcb->Threads) foreach (auto thread in process->Threads)
{ {
if (InvalidTCB(tcb)) if (InvalidTCB(thread))
continue; continue;
if (tcb->Status != TaskStatus::Ready) if (thread->Status != TaskStatus::Ready)
continue; continue;
if (tcb->Info.Affinity[CurrentCPU->ID] == false) if (thread->Info.Affinity[CurrentCPU->ID] == false)
continue; continue;
CurrentCPU->CurrentProcess = pcb; CurrentCPU->CurrentProcess = process;
CurrentCPU->CurrentThread = tcb; CurrentCPU->CurrentThread = thread;
return true; return true;
} }
} }
@ -152,7 +156,7 @@ namespace Tasking
return false; return false;
} }
SafeFunction __no_instrument_function bool Task::GetNextAvailableThread(void *CPUDataPointer) SafeFunction NIF bool Task::GetNextAvailableThread(void *CPUDataPointer)
{ {
CPUData *CurrentCPU = (CPUData *)CPUDataPointer; CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
@ -162,94 +166,103 @@ namespace Tasking
{ {
size_t TempIndex = i; size_t TempIndex = i;
RetryAnotherThread: RetryAnotherThread:
TCB *thread = CurrentCPU->CurrentProcess->Threads[TempIndex + 1]; TCB *nextThread = CurrentCPU->CurrentProcess->Threads[TempIndex + 1];
if (unlikely(InvalidTCB(thread)))
if (unlikely(InvalidTCB(nextThread)))
{ {
if (TempIndex > CurrentCPU->CurrentProcess->Threads.size()) if (TempIndex > CurrentCPU->CurrentProcess->Threads.size())
break; break;
TempIndex++; TempIndex++;
gnat_schedbg("Thread %#lx is invalid", thread);
gnat_schedbg("Thread %#lx is invalid", nextThread);
goto RetryAnotherThread; goto RetryAnotherThread;
} }
gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)", CurrentCPU->CurrentProcess->Threads[i]->Name, CurrentCPU->CurrentProcess->Threads[i]->ID, thread->Name, thread->ID); gnat_schedbg("\"%s\"(%d) and next thread is \"%s\"(%d)",
CurrentCPU->CurrentProcess->Threads[i]->Name,
CurrentCPU->CurrentProcess->Threads[i]->ID,
thread->Name, thread->ID);
if (thread->Status != TaskStatus::Ready) if (nextThread->Status != TaskStatus::Ready)
{ {
gnat_schedbg("Thread %d is not ready", thread->ID); gnat_schedbg("Thread %d is not ready", nextThread->ID);
TempIndex++; TempIndex++;
goto RetryAnotherThread; goto RetryAnotherThread;
} }
if (thread->Info.Affinity[CurrentCPU->ID] == false) if (nextThread->Info.Affinity[CurrentCPU->ID] == false)
continue; continue;
CurrentCPU->CurrentThread = thread; CurrentCPU->CurrentThread = nextThread;
gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", thread->ID, thread->Parent->Name, CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size()); gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d",
thread->ID, thread->Parent->Name,
CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size());
return true; return true;
} }
#ifdef DEBUG #ifdef DEBUG
else else
{ {
gnat_schedbg("Thread %d is not the current one", CurrentCPU->CurrentProcess->Threads[i]->ID); gnat_schedbg("Thread %d is not the current one",
CurrentCPU->CurrentProcess->Threads[i]->ID);
} }
#endif #endif
} }
return false; return false;
} }
SafeFunction __no_instrument_function bool Task::GetNextAvailableProcess(void *CPUDataPointer) SafeFunction NIF bool Task::GetNextAvailableProcess(void *CPUDataPointer)
{ {
CPUData *CurrentCPU = (CPUData *)CPUDataPointer; CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
bool Skip = true; bool Skip = true;
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (pcb == CurrentCPU->CurrentProcess.Load()) if (process == CurrentCPU->CurrentProcess.Load())
{ {
Skip = false; Skip = false;
gnap_schedbg("Found current process %#lx", pcb); gnap_schedbg("Found current process %#lx", process);
continue; continue;
} }
if (Skip) if (Skip)
{ {
gnap_schedbg("Skipping process %#lx", pcb); gnap_schedbg("Skipping process %#lx", process);
continue; continue;
} }
if (InvalidPCB(pcb)) if (InvalidPCB(process))
{ {
gnap_schedbg("Invalid process %#lx", pcb); gnap_schedbg("Invalid process %#lx", process);
continue; continue;
} }
if (pcb->Status != TaskStatus::Ready) if (process->Status != TaskStatus::Ready)
{ {
gnap_schedbg("Process %d is not ready", pcb->ID); gnap_schedbg("Process %d is not ready", process->ID);
continue; continue;
} }
foreach (auto tcb in pcb->Threads) foreach (auto thread in process->Threads)
{ {
if (InvalidTCB(tcb)) if (InvalidTCB(thread))
{ {
gnap_schedbg("Invalid thread %#lx", tcb); gnap_schedbg("Invalid thread %#lx", thread);
continue; continue;
} }
if (tcb->Status != TaskStatus::Ready) if (thread->Status != TaskStatus::Ready)
{ {
gnap_schedbg("Thread %d is not ready", tcb->ID); gnap_schedbg("Thread %d is not ready", thread->ID);
continue; continue;
} }
if (tcb->Info.Affinity[CurrentCPU->ID] == false) if (thread->Info.Affinity[CurrentCPU->ID] == false)
continue; continue;
CurrentCPU->CurrentProcess = pcb; CurrentCPU->CurrentProcess = process;
CurrentCPU->CurrentThread = tcb; CurrentCPU->CurrentThread = thread;
gnap_schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", tcb->ID, tcb->Name, pcb->Threads.size(), ListProcess.size()); gnap_schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)",
thread->ID, thread->Name, process->Threads.size(), ListProcess.size());
return true; return true;
} }
} }
@ -257,75 +270,76 @@ namespace Tasking
return false; return false;
} }
SafeFunction __no_instrument_function void Task::SchedulerCleanupProcesses() SafeFunction NIF void Task::SchedulerCleanupProcesses()
{ {
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(process))
continue; continue;
RemoveProcess(pcb); RemoveProcess(process);
} }
} }
SafeFunction __no_instrument_function bool Task::SchedulerSearchProcessThread(void *CPUDataPointer) SafeFunction NIF bool Task::SchedulerSearchProcessThread(void *CPUDataPointer)
{ {
CPUData *CurrentCPU = (CPUData *)CPUDataPointer; CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(process))
{ {
sspt_schedbg("Invalid process %#lx", pcb); sspt_schedbg("Invalid process %#lx", process);
continue; continue;
} }
if (pcb->Status != TaskStatus::Ready) if (process->Status != TaskStatus::Ready)
{ {
sspt_schedbg("Process %d is not ready", pcb->ID); sspt_schedbg("Process %d is not ready", process->ID);
continue; continue;
} }
foreach (auto tcb in pcb->Threads) foreach (auto thread in process->Threads)
{ {
if (InvalidTCB(tcb)) if (InvalidTCB(thread))
{ {
sspt_schedbg("Invalid thread %#lx", tcb); sspt_schedbg("Invalid thread %#lx", thread);
continue; continue;
} }
if (tcb->Status != TaskStatus::Ready) if (thread->Status != TaskStatus::Ready)
{ {
sspt_schedbg("Thread %d is not ready", tcb->ID); sspt_schedbg("Thread %d is not ready", thread->ID);
continue; continue;
} }
if (tcb->Info.Affinity[CurrentCPU->ID] == false) if (thread->Info.Affinity[CurrentCPU->ID] == false)
continue; continue;
CurrentCPU->CurrentProcess = pcb; CurrentCPU->CurrentProcess = process;
CurrentCPU->CurrentThread = tcb; CurrentCPU->CurrentThread = thread;
sspt_schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", tcb->ID, tcb->Parent->Name, pcb->Threads.size(), ListProcess.size()); sspt_schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)",
thread->ID, thread->Parent->Name, process->Threads.size(), ListProcess.size());
return true; return true;
} }
} }
return false; return false;
} }
SafeFunction __no_instrument_function void Task::UpdateProcessStatus() SafeFunction NIF void Task::UpdateProcessStatus()
{ {
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(process))
continue; continue;
if (pcb->Status == TaskStatus::Terminated || if (process->Status == TaskStatus::Terminated ||
pcb->Status == TaskStatus::Stopped) process->Status == TaskStatus::Stopped)
continue; continue;
bool AllThreadsSleeping = true; bool AllThreadsSleeping = true;
foreach (auto tcb in pcb->Threads) foreach (auto thread in process->Threads)
{ {
if (tcb->Status != TaskStatus::Sleeping) if (thread->Status != TaskStatus::Sleeping)
{ {
AllThreadsSleeping = false; AllThreadsSleeping = false;
break; break;
@ -333,45 +347,46 @@ namespace Tasking
} }
if (AllThreadsSleeping) if (AllThreadsSleeping)
pcb->Status = TaskStatus::Sleeping; process->Status = TaskStatus::Sleeping;
else if (pcb->Status == TaskStatus::Sleeping) else if (process->Status == TaskStatus::Sleeping)
pcb->Status = TaskStatus::Ready; process->Status = TaskStatus::Ready;
} }
} }
SafeFunction __no_instrument_function void Task::WakeUpThreads(void *CPUDataPointer) SafeFunction NIF void Task::WakeUpThreads(void *CPUDataPointer)
{ {
CPUData *CurrentCPU = (CPUData *)CPUDataPointer; CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
foreach (auto pcb in ListProcess) foreach (auto process in ListProcess)
{ {
if (InvalidPCB(pcb)) if (InvalidPCB(process))
continue; continue;
if (pcb->Status == TaskStatus::Terminated || if (process->Status == TaskStatus::Terminated ||
pcb->Status == TaskStatus::Stopped) process->Status == TaskStatus::Stopped)
continue; continue;
foreach (auto tcb in pcb->Threads) foreach (auto thread in process->Threads)
{ {
if (InvalidTCB(tcb)) if (InvalidTCB(thread))
continue; continue;
if (tcb->Status != TaskStatus::Sleeping) if (thread->Status != TaskStatus::Sleeping)
continue; continue;
/* Check if the thread is ready to wake up. */ /* Check if the thread is ready to wake up. */
if (tcb->Info.SleepUntil < TimeManager->GetCounter()) if (thread->Info.SleepUntil < TimeManager->GetCounter())
{ {
if (pcb->Status == TaskStatus::Sleeping) if (process->Status == TaskStatus::Sleeping)
pcb->Status = TaskStatus::Ready; process->Status = TaskStatus::Ready;
tcb->Status = TaskStatus::Ready; thread->Status = TaskStatus::Ready;
tcb->Info.SleepUntil = 0; thread->Info.SleepUntil = 0;
wut_schedbg("Thread \"%s\"(%d) woke up.", tcb->Name, tcb->ID); wut_schedbg("Thread \"%s\"(%d) woke up.", thread->Name, thread->ID);
} }
else else
{ {
wut_schedbg("Thread \"%s\"(%d) is not ready to wake up. (SleepUntil: %d, Counter: %d)", tcb->Name, tcb->ID, tcb->Info.SleepUntil, TimeManager->GetCounter()); wut_schedbg("Thread \"%s\"(%d) is not ready to wake up. (SleepUntil: %d, Counter: %d)",
thread->Name, thread->ID, thread->Info.SleepUntil, TimeManager->GetCounter());
} }
} }
} }
@ -408,7 +423,7 @@ namespace Tasking
"SchedulerSearchProcessThread", "SchedulerSearchProcessThread",
}; };
SafeFunction __no_instrument_function void OnScreenTaskManagerUpdate() SafeFunction NIF void OnScreenTaskManagerUpdate()
{ {
TimeManager->Sleep(100); TimeManager->Sleep(100);
Video::ScreenBuffer *sb = Display->GetBuffer(0); Video::ScreenBuffer *sb = Display->GetBuffer(0);
@ -448,7 +463,7 @@ namespace Tasking
} }
#endif #endif
SafeFunction __no_instrument_function void Task::Schedule(CPU::x64::TrapFrame *Frame) SafeFunction NIF void Task::Schedule(CPU::x64::TrapFrame *Frame)
{ {
SmartCriticalSection(SchedulerLock); SmartCriticalSection(SchedulerLock);
if (StopScheduler) if (StopScheduler)
@ -599,7 +614,8 @@ namespace Tasking
// wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs); // wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs);
break; break;
default: default:
error("Unknown trust level %d.", CurrentCPU->CurrentProcess->Security.TrustLevel); error("Unknown trust level %d.",
CurrentCPU->CurrentProcess->Security.TrustLevel);
break; break;
} }
@ -628,7 +644,8 @@ namespace Tasking
CurrentCPU->CurrentThread->Registers.rsp); CurrentCPU->CurrentThread->Registers.rsp);
schedbg("================================================================"); schedbg("================================================================");
schedbg("Technical Informations on Thread %s[%ld]:", CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID); schedbg("Technical Informations on Thread %s[%ld]:",
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID);
uint64_t ds; uint64_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
@ -653,7 +670,7 @@ namespace Tasking
__sync; /* TODO: Is this really needed? */ __sync; /* TODO: Is this really needed? */
} }
SafeFunction __no_instrument_function void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) { this->Schedule(Frame); } SafeFunction NIF void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) { this->Schedule(Frame); }
#elif defined(__i386__) #elif defined(__i386__)
SafeFunction bool Task::FindNewProcess(void *CPUDataPointer) SafeFunction bool Task::FindNewProcess(void *CPUDataPointer)
{ {

View File

@ -130,20 +130,17 @@ namespace CPU
/** /**
* @brief Stop the CPU (infinite loop) * @brief Stop the CPU (infinite loop)
*/ */
SafeFunction static inline void Stop() SafeFunction __noreturn __naked __used inline void Stop()
{ {
while (1)
{
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("CPUStopLoop:\n" asmv("CPUStopLoop:\n"
"cli\n" "cli\n"
"hlt\n" "hlt\n"
"jmp CPUStopLoop"); "jmp CPUStopLoop");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("msr daifset, #2"); asmv("msr daifset, #2");
asmv("wfe"); asmv("wfe");
#endif #endif
}
} }
/** /**

View File

@ -16,7 +16,7 @@ private:
public: public:
typedef T *iterator; typedef T *iterator;
__no_instrument_function Vector() NIF Vector()
{ {
#ifdef DEBUG_MEM_ALLOCATION #ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: Vector( )"); debug("VECTOR INIT: Vector( )");
@ -26,7 +26,7 @@ public:
VectorBuffer = 0; VectorBuffer = 0;
} }
__no_instrument_function Vector(size_t Size) NIF Vector(size_t Size)
{ {
VectorCapacity = Size; VectorCapacity = Size;
VectorSize = Size; VectorSize = Size;
@ -36,7 +36,7 @@ public:
VectorBuffer = new T[Size]; VectorBuffer = new T[Size];
} }
__no_instrument_function Vector(size_t Size, const T &Initial) NIF Vector(size_t Size, const T &Initial)
{ {
VectorSize = Size; VectorSize = Size;
VectorCapacity = Size; VectorCapacity = Size;
@ -49,7 +49,7 @@ public:
VectorBuffer[i] = Initial; VectorBuffer[i] = Initial;
} }
__no_instrument_function Vector(const Vector<T> &Vector) NIF Vector(const Vector<T> &Vector)
{ {
VectorSize = Vector.VectorSize; VectorSize = Vector.VectorSize;
VectorCapacity = Vector.VectorCapacity; VectorCapacity = Vector.VectorCapacity;
@ -62,11 +62,13 @@ public:
VectorBuffer[i] = Vector.VectorBuffer[i]; VectorBuffer[i] = Vector.VectorBuffer[i];
} }
__no_instrument_function ~Vector() NIF ~Vector()
{ {
#ifdef DEBUG_MEM_ALLOCATION #ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: ~Vector( ~%lx )", VectorBuffer); debug("VECTOR INIT: ~Vector( ~%lx )", VectorBuffer);
#endif #endif
VectorSize = 0;
VectorCapacity = 0;
if (VectorBuffer != nullptr) if (VectorBuffer != nullptr)
{ {
delete[] VectorBuffer; delete[] VectorBuffer;
@ -74,7 +76,7 @@ public:
} }
} }
__no_instrument_function void remove(size_t Position) NIF void remove(size_t Position)
{ {
if (Position >= VectorSize) if (Position >= VectorSize)
return; return;
@ -86,7 +88,7 @@ public:
VectorSize--; VectorSize--;
} }
__no_instrument_function void remove(const T &Value) NIF void remove(const T &Value)
{ {
for (size_t i = 0; i < VectorSize; i++) for (size_t i = 0; i < VectorSize; i++)
{ {
@ -98,30 +100,91 @@ public:
} }
} }
__no_instrument_function size_t capacity() const { return VectorCapacity; } NIF T &null_elem()
{
static T null_elem;
return null_elem;
}
__no_instrument_function size_t size() const { return VectorSize; } NIF bool null_elem(size_t Index)
{
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
return false;
return true;
}
__no_instrument_function bool empty() const; NIF T &next(size_t Position)
{
if (Position + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[Position + 1]))
return VectorBuffer[Position + 1];
warn("next( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
return this->null_elem();
}
__no_instrument_function iterator begin() { return VectorBuffer; } NIF T &prev(size_t Position)
{
if (Position > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[Position - 1]))
return VectorBuffer[Position - 1];
warn("prev( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
return this->null_elem();
}
__no_instrument_function iterator end() { return VectorBuffer + size(); } NIF T &next(const T &Value)
{
for (size_t i = 0; i < VectorSize; i++)
{
if (VectorBuffer[i] == Value)
{
if (i + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[i + 1]))
return VectorBuffer[i + 1];
else
break;
}
}
warn("next( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
return this->null_elem();
}
__no_instrument_function T &front() { return VectorBuffer[0]; } NIF T &prev(const T &Value)
{
for (size_t i = 0; i < VectorSize; i++)
{
if (VectorBuffer[i] == Value)
{
if (i > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[i - 1]))
return VectorBuffer[i - 1];
else
break;
}
}
warn("prev( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
return this->null_elem();
}
__no_instrument_function T &back() { return VectorBuffer[VectorSize - 1]; } NIF size_t capacity() const { return VectorCapacity; }
__no_instrument_function void push_back(const T &Value) NIF size_t size() const { return VectorSize; }
NIF bool empty() const;
NIF iterator begin() { return VectorBuffer; }
NIF iterator end() { return VectorBuffer + size(); }
NIF T &front() { return VectorBuffer[0]; }
NIF T &back() { return VectorBuffer[VectorSize - 1]; }
NIF void push_back(const T &Value)
{ {
if (VectorSize >= VectorCapacity) if (VectorSize >= VectorCapacity)
reserve(VectorCapacity + 5); reserve(VectorCapacity + 5);
VectorBuffer[VectorSize++] = Value; VectorBuffer[VectorSize++] = Value;
} }
__no_instrument_function void pop_back() { VectorSize--; } NIF void pop_back() { VectorSize--; }
__no_instrument_function void reverse() NIF void reverse()
{ {
if (VectorSize <= 1) if (VectorSize <= 1)
return; return;
@ -133,7 +196,7 @@ public:
} }
} }
__no_instrument_function void reserve(size_t Capacity) NIF void reserve(size_t Capacity)
{ {
if (VectorBuffer == 0) if (VectorBuffer == 0)
{ {
@ -155,24 +218,36 @@ public:
VectorBuffer = NewBuffer; VectorBuffer = NewBuffer;
} }
__no_instrument_function void resize(size_t Size) NIF void resize(size_t Size)
{ {
reserve(Size); reserve(Size);
VectorSize = Size; VectorSize = Size;
} }
__no_instrument_function T &operator[](size_t Index) NIF void clear()
{
VectorCapacity = 0;
VectorSize = 0;
if (VectorBuffer != nullptr)
{
delete[] VectorBuffer;
VectorBuffer = nullptr;
}
}
NIF T *data() { return VectorBuffer; }
NIF T &operator[](size_t Index)
{ {
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index])) if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
{ {
warn("operator[]( %lld ) is null (requested by %#lx)", Index, __builtin_return_address(0)); warn("operator[]( %lld ) is null (requested by %#lx)", Index, __builtin_return_address(0));
static T null_elem; return this->null_elem();
return null_elem;
} }
return VectorBuffer[Index]; return VectorBuffer[Index];
} }
__no_instrument_function Vector<T> &operator=(const Vector<T> &Vector) NIF Vector<T> &operator=(const Vector<T> &Vector)
{ {
delete[] VectorBuffer; delete[] VectorBuffer;
VectorSize = Vector.VectorSize; VectorSize = Vector.VectorSize;
@ -185,19 +260,6 @@ public:
VectorBuffer[i] = Vector.VectorBuffer[i]; VectorBuffer[i] = Vector.VectorBuffer[i];
return *this; return *this;
} }
__no_instrument_function void clear()
{
VectorCapacity = 0;
VectorSize = 0;
if (VectorBuffer != nullptr)
{
delete[] VectorBuffer;
VectorBuffer = nullptr;
}
}
__no_instrument_function T *data() { return VectorBuffer; }
}; };
#endif // !__FENNIX_KERNEL_VECTOR_H__ #endif // !__FENNIX_KERNEL_VECTOR_H__