mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-10 23:09:18 +00:00
Update kernel
This commit is contained in:
@ -73,7 +73,7 @@ void lsof()
|
||||
fd.Handle->node->FullPath);
|
||||
}
|
||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||
if (!Config.BootAnimation)
|
||||
if (!Config.Quiet)
|
||||
Display->SetBuffer(0);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
140
tests/stress.cpp
Normal 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
|
@ -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
36
tests/task_heartbeat.cpp
Normal 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
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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__));
|
||||
|
Reference in New Issue
Block a user