Update kernel

This commit is contained in:
EnderIce2
2024-01-19 06:47:42 +02:00
parent fd15592608
commit 96daa43d38
282 changed files with 25486 additions and 15700 deletions

View File

@ -73,7 +73,7 @@ void lsof()
fd.Handle->node->FullPath);
}
Display->SetBufferCursor(0, tmpX, tmpY);
if (!Config.BootAnimation)
if (!Config.Quiet)
Display->SetBuffer(0);
}
}

View File

@ -18,6 +18,7 @@
#ifdef DEBUG
#include <types.h>
#include <filesystem/ioctl.hpp>
#include <memory/macro.hpp>
#include <memory/vma.hpp>
#include <assert.h>
@ -46,12 +47,11 @@
#endif // UINTPTR_MAX != UINT64_MAX
#endif // aa64
void TestSeekMacros()
{
static_assert(sc_SEEK_SET == SEEK_SET);
static_assert(sc_SEEK_CUR == SEEK_CUR);
static_assert(sc_SEEK_END == SEEK_END);
}
static_assert(sc_SEEK_SET == SEEK_SET);
static_assert(sc_SEEK_CUR == SEEK_CUR);
static_assert(sc_SEEK_END == SEEK_END);
static_assert(TIOCGPTN == 0x80045430);
static_assert(TIOCSPTLCK == 0x40045431);
__constructor void TestMacros()
{
@ -154,6 +154,17 @@ __constructor void TestMacros()
inf_loop;
}
}
{
constexpr int x = 5;
constexpr int y = 10;
constexpr int max_result = MAX(x, y);
constexpr int min_result = MIN(x, y);
static_assert(max_result == 10);
static_assert(min_result == 5);
}
}
#endif // DEBUG

View File

@ -21,33 +21,111 @@
#include <debug.h>
#include <string>
#include "../kernel.h"
/* Originally from: https://github.com/EnderIce2/FennixProject/blob/main/kernel/test.cpp */
#define MEMTEST_ITERATIONS 1024
#define MAX_SIZE 1024
void testMemoryIntegrity()
{
debug("Testing memory integrity...");
for (size_t i = 1; i <= MAX_SIZE; i *= 2)
{
void *ptr1 = malloc(i);
if (ptr1 == NULL)
{
error("malloc failed for size %zu", i);
inf_loop;
}
memset(ptr1, 0xAA, i);
for (size_t j = 0; j < i; ++j)
{
if (*((unsigned char *)ptr1 + j) != 0xAA)
{
error("Memory corruption detected before free (size %zu)", i);
inf_loop;
}
}
void *ptr2 = malloc(i * 2);
if (ptr2 == NULL)
{
error("malloc failed for size %zu", i * 2);
inf_loop;
}
memset(ptr2, 0xBB, i * 2);
for (size_t j = 0; j < i; ++j)
{
if (*((unsigned char *)ptr1 + j) != 0xAA)
{
error("Memory corruption detected in previous allocation (size %zu)", i);
inf_loop;
}
}
free(ptr1);
for (size_t j = 0; j < i; ++j)
{
if (*((unsigned char *)ptr2 + j) != 0xBB)
{
error("Memory corruption detected in current allocation (size %zu)", i * 2);
inf_loop;
}
}
void *ptr3 = realloc(ptr2, i * 3);
if (ptr3 == NULL)
{
error("realloc failed for size %zu", i * 3);
inf_loop;
}
memset(ptr3, 0xCC, i * 3);
for (size_t j = 0; j < i; ++j)
{
if (*((unsigned char *)ptr3 + j) != 0xCC)
{
error("Memory corruption detected after realloc (size %zu)", i * 3);
inf_loop;
}
}
free(ptr3);
}
debug("Memory integrity test passed.");
}
class test_mem_new_delete
{
public:
test_mem_new_delete();
~test_mem_new_delete();
test_mem_new_delete()
{
for (char i = 0; i < 2; i++)
;
}
~test_mem_new_delete()
{
for (char i = 0; i < 2; i++)
;
}
};
test_mem_new_delete::test_mem_new_delete()
{
for (char i = 0; i < 2; i++)
;
}
test_mem_new_delete::~test_mem_new_delete()
{
for (char i = 0; i < 2; i++)
;
}
extern bool DebuggerIsAttached;
void TestMemoryAllocation()
{
return; /* Bit annoying to have to wait for this to finish */
#ifdef a32
return; /* Not ready for now. */
#endif
@ -57,6 +135,8 @@ void TestMemoryAllocation()
return;
}
testMemoryIntegrity();
void *tmpAlloc1 = kmalloc(176);
void *tmpAlloc2 = kmalloc(511);
void *tmpAlloc3 = kmalloc(1027);
@ -113,7 +193,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("Multiple Dynamic Malloc Test");
@ -128,7 +209,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("New/Delete Test");
@ -146,7 +228,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("New/Delete Fixed Array Test");
@ -164,7 +247,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("New/Delete Dynamic Array Test");
@ -184,7 +268,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("calloc Test");
@ -202,7 +287,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
debug("realloc Test");
@ -221,7 +307,8 @@ void TestMemoryAllocation()
kfree((void *)prq2);
debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
assert(prq1 == prq2);
if (Config.AllocatorType != Memory::MemoryAllocatorType::rpmalloc_)
assert(prq1 == prq2);
}
}

View File

@ -18,8 +18,10 @@
#ifdef DEBUG
#include <assert.h>
#include <unordered_map>
#include <vector>
#include <atomic>
#include <list>
void Test_std()
{
@ -63,6 +65,76 @@ void Test_std()
debug("3: %#lx", intVector[3]);
debug("4: %#lx", intVector[4]);
/* ---------------------------- */
std::list<int> intList;
intList.push_back(10);
intList.push_back(20);
intList.push_back(30);
assert(intList.size() == 3);
assert(intList.front() == 10);
assert(intList.back() == 30);
intList.pop_back();
assert(intList.size() == 2);
intList.clear();
assert(intList.empty());
/* ---------------------------- */
std::unordered_map<int, int> intMap;
intMap[1] = 10;
intMap[2] = 20;
intMap[3] = 30;
assert(intMap.size() == 3);
assert(intMap[1] == 10);
assert(intMap[2] == 20);
assert(intMap[3] == 30);
intMap.erase(1);
assert(intMap.size() == 2);
intMap.clear();
assert(intMap.empty());
std::unordered_map<const char *, int> strMap;
strMap["hello"] = 10;
strMap["world"] = 20;
strMap["foo"] = 30;
assert(strMap.size() == 3);
assert(strMap["hello"] == 10);
assert(strMap["world"] == 20);
assert(strMap["foo"] == 30);
strMap.erase("hello");
assert(strMap.size() == 2);
strMap.clear();
assert(strMap.empty());
/* ---------------------------- */
std::hash<int> intHash;
size_t a0 = intHash(0xdeadbeef);
size_t a1 = intHash(0xdeadbeef);
size_t a2 = intHash(1);
size_t a3 = intHash(2);
debug("a0: %#lx", a0);
debug("a1: %#lx", a1);
debug("a2: %#lx", a2);
debug("a3: %#lx", a3);
assert(a0 == a1);
assert(a2 != a3);
/* ---------------------------- */
debug("std: OK");
}

View File

@ -137,7 +137,7 @@ void TestString()
else
{
error("String addition doesn't work! \"%s\"", c.c_str());
inf_loop;
// inf_loop;
}
for (int i = 0; i < 1024; i++)

140
tests/stress.cpp Normal file
View File

@ -0,0 +1,140 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef DEBUG
#include "t.h"
#include "../kernel.h"
void killChildren(Tasking::PCB *pcb)
{
if (pcb->Children.empty())
{
KPrint("Process %s(%d) has no children", pcb->Name, pcb->ID);
return;
}
std::list<Tasking::PCB *> children = pcb->Children;
foreach (auto child in children)
{
if (child->State.load() == Tasking::Terminated)
{
KPrint("Process %s(%d) is already dead", child->Name, child->ID);
continue;
}
KPrint("Killing %s(%d)", child->Name, child->ID);
killChildren(child);
child->SetState(Tasking::Terminated);
debug("killed %s(%d)", child->Name, child->ID);
}
}
constexpr size_t chunk = 10 * 1024 * 1024; /* 10 MiB */
std::atomic_size_t totalAllocated = 0;
std::atomic_size_t highestScore = 0;
std::atomic_bool halt_fork = false;
std::list<void *> allocatedChunks;
Tasking::PCB *baseProc = nullptr;
Tasking::PCB *lastProc = nullptr;
std::atomic_bool hold = false;
void StressKernel()
{
return;
static int once = 0;
if (!once++)
{
debug("We have %d GiB of free memory",
TO_GiB(KernelAllocator.GetFreeMemory()));
assert(TO_GiB(KernelAllocator.GetFreeMemory()) >= 1);
}
while (true)
{
while (hold.exchange(true, std::memory_order_acquire))
;
if (!halt_fork.load() && TaskManager->GetProcessList().size() > 100)
halt_fork.store(true);
void *ptr;
Tasking::PCB *pcb = nullptr;
if (TO_MiB(KernelAllocator.GetFreeMemory()) < 20)
{
KPrint("\eE85230Not enough memory left!");
goto End;
}
ptr = KernelAllocator.RequestPages(TO_PAGES(chunk));
if (ptr == nullptr)
{
KPrint("\eE85230Failed to allocate memory!");
KPrint("Score is: %d MiB (current is %d MiB)",
TO_MiB(highestScore.load()), TO_MiB(totalAllocated.load()));
continue;
}
KPrint("Allocated %d bytes at %#lx", chunk, ptr);
allocatedChunks.push_back(ptr);
totalAllocated.fetch_add(chunk);
if (totalAllocated.load() > highestScore.load())
highestScore.store(totalAllocated.load());
KPrint("Total allocated: %d MiB [KERNEL: %d MiB free]",
TO_MiB(totalAllocated.load()), TO_MiB(KernelAllocator.GetFreeMemory()));
if (lastProc == nullptr)
lastProc = thisProcess;
if (halt_fork.load() == false)
{
KPrint("Forking...");
pcb = TaskManager->CreateProcess(lastProc, "STRESS TEST", Tasking::Kernel);
lastProc = pcb;
if (baseProc == nullptr)
baseProc = pcb;
TaskManager->CreateThread(pcb, Tasking::IP(StressKernel));
KPrint("There are %d processes", TaskManager->GetProcessList().size());
}
End:
hold.store(true);
if (TO_GiB(totalAllocated.load()) >= 1)
{
KPrint("Freeing memory...");
forItr(itr, allocatedChunks)
{
KPrint("Freeing %#lx", *itr);
KernelAllocator.FreePages(*itr, TO_PAGES(chunk));
allocatedChunks.erase(itr);
}
totalAllocated.store(0);
}
// if (TaskManager->GetProcessList().size() >= 100)
// {
// KPrint("Killing processes...");
// killChildren(baseProc->Children.front());
// KPrint("All processes killed.");
// baseProc = nullptr;
// }
hold.store(false);
}
}
#endif // DEBUG

View File

@ -30,6 +30,8 @@ void tasking_test_mutex();
void lsof();
void TaskMgr();
void TreeFS(vfs::Node *node, int Depth);
void TaskHeartbeat();
void StressKernel();
#endif // DEBUG
#endif // !__FENNIX_KERNEL_non_constructor_tests_H__

36
tests/task_heartbeat.cpp Normal file
View File

@ -0,0 +1,36 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef DEBUG
#include "t.h"
#include "../kernel.h"
void TaskHeartbeat()
{
thisThread->Rename("Task Heartbeat");
thisThread->SetPriority(Tasking::Idle);
while (true)
{
debug("Task Heartbeat");
TaskManager->Sleep(5000);
}
}
#endif // DEBUG

View File

@ -153,12 +153,12 @@ void TaskMgr()
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[State], Thd->Name, StatusesSign[State], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.rip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbol(Thd->Registers.rip) : "unknown");
#elif defined(a32)
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#x \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[State], Thd->Name, StatusesSign[State], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.eip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbol(Thd->Registers.eip) : "unknown");
#elif defined(aa64)
#endif
}
@ -177,7 +177,7 @@ void TaskMgr()
if (sanity > 1000)
sanity = 0;
Display->SetBufferCursor(0, tmpX, tmpY);
if (!Config.BootAnimation)
if (!Config.Quiet)
Display->SetBuffer(0);
TaskManager->Sleep(100);

View File

@ -28,7 +28,7 @@ void TreeFS(vfs::Node *node, int Depth)
{
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
if (!Config.BootAnimation)
if (!Config.Quiet)
Display->SetBuffer(0);
TaskManager->Sleep(100);
TreeFS(Chld, Depth + 1);

View File

@ -21,6 +21,7 @@
__constructor void TestTypeSize()
{
return;
debug("--- INT TYPES ---");
debug("sizeof(__INT8_TYPE__) = %lld", sizeof(__INT8_TYPE__));
debug("sizeof(__INT16_TYPE__) = %lld", sizeof(__INT16_TYPE__));