Add UserTime and KernelTime tracker

This commit is contained in:
Alex 2023-04-25 05:12:58 +03:00
parent 03b667f5c0
commit 299c919d1d
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
6 changed files with 122 additions and 119 deletions

View File

@ -81,6 +81,7 @@ LockClass mExtTrkLock;
* - [?] Somewhere in the kernel, the memory is wrongly freed or memcpy/memset.
* - [ ] GlobalDescriptorTable::SetKernelStack() is not working properly.
* - [ ] Sometimes while the kernel is inside BeforeShutdown(), we end up in a deadlock.
* - [ ] CPU usage is not working properly.
*
* CREDITS AND REFERENCES:
* - General:
@ -200,8 +201,6 @@ Time::time *TimeManager = nullptr;
VirtualFileSystem::Virtual *vfs = nullptr;
VirtualFileSystem::Virtual *bootanim_vfs = nullptr;
Time::Clock BootClock;
KernelConfig Config = {
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
.SchedulerType = 1,
@ -254,18 +253,23 @@ EXTERNC void KPrint(const char *Format, ...)
EXTERNC NIF void Main(BootInfo *Info)
{
BootClock = Time::ReadClock();
memcpy(&bInfo, Info, sizeof(BootInfo));
debug("BootInfo structure is at %p", bInfo);
Display = new Video::Display(bInfo.Framebuffer[0]);
KPrint("%s - %s [\e058C19%s\eFFFFFF]", KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
/**************************************************************************************/
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
if (DebuggerIsAttached)
KPrint("\eFFA500Kernel debugger detected.");
/**************************************************************************************/
KPrint("Initializing GDT and IDT");
Interrupts::Initialize(0);
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)Info->Kernel.FileBase);
KPrint("Reading Kernel Parameters");
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
@ -286,15 +290,23 @@ EXTERNC NIF void Main(BootInfo *Info)
KPrint("Initializing CPU Features");
CPU::InitializeFeatures(0);
if (DebuggerIsAttached)
KPrint("\eFFA500Kernel debugger detected.");
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)Info->Kernel.FileBase);
KPrint("Initializing Power Manager");
PowerManager = new Power::Power;
#if defined(a64)
PowerManager->InitDSDT();
#elif defined(a32)
// FIXME: Add ACPI support for i386
#elif defined(aa64)
#endif
KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0);
KPrint("Initializing Timers");
TimeManager = new Time::time;
TimeManager->FindTimers(PowerManager->GetACPI());
KPrint("Initializing PCI Manager");
PCIManager = new PCI::PCI;
@ -308,20 +320,6 @@ EXTERNC NIF void Main(BootInfo *Info)
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
}
KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0);
#if defined(a64)
PowerManager->InitDSDT();
#elif defined(a32)
// FIXME: Add ACPI support for i386
#elif defined(aa64)
#endif
KPrint("Initializing Timers");
TimeManager = new Time::time;
TimeManager->FindTimers(PowerManager->GetACPI());
KPrint("Initializing Bootstrap Processor Timer");
Interrupts::InitializeTimer(0);

View File

@ -92,16 +92,53 @@ const char *SuccessSourceStrings[] = {
"SchedulerSearchProcessThread",
};
void TaskMgr()
void TaskMgr_Dummy100Usage()
{
while (1)
;
}
void TaskMgr_Dummy0Usage()
{
while (1)
TaskManager->Sleep(1000000);
}
uint64_t GetUsage(uint64_t OldSystemTime, Tasking::TaskInfo *Info)
{
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
if (Info->OldKernelTime || Info->OldUserTime)
{
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
CpuUsage = CpuUsage * 100;
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
// CurrentTime, OldTime, SystemTime, CpuUsage);
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return CpuUsage;
}
Info->OldKernelTime = Info->KernelTime;
Info->OldUserTime = Info->UserTime;
return 0;
}
void TaskMgr()
{
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage");
TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage");
while (1)
{
CPU::Interrupts(CPU::Disable);
static int sanity = 0;
Video::ScreenBuffer *sb = Display->GetBuffer(0);
for (short i = 0; i < 340; i++)
for (short i = 0; i < 500; i++)
{
for (short j = 0; j < 200; j++)
for (short j = 0; j < 500; j++)
{
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
*Pixel = 0x222222;
@ -112,19 +149,23 @@ void TaskMgr()
Display->GetBufferCursor(0, &tmpX, &tmpY);
Display->SetBufferCursor(0, 0, 0);
printf("\eF02C21Task Manager\n");
static uint64_t OldSystemTime = 0;
foreach (auto Proc in TaskManager->GetProcessList())
{
int Status = Proc->Status;
printf("\e%s-> \eAABBCC%s \e00AAAA%s\n",
Statuses[Status], Proc->Name, StatusesSign[Status]);
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
foreach (auto Thd in Proc->Threads)
{
Status = Thd->Status;
printf(" \e%s-> \eAABBCC%s \e00AAAA%s\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status]);
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime, Thd->Info.UserTime);
}
}
OldSystemTime = TimeManager->GetCounter();
#if defined(a64)
register uintptr_t CurrentStackAddress asm("rsp");
#elif defined(a32)
@ -138,7 +179,8 @@ void TaskMgr()
Display->SetBufferCursor(0, tmpX, tmpY);
if (!Config.BootAnimation)
Display->SetBuffer(0);
CPU::Interrupts(CPU::Enable);
TaskManager->Sleep(100);
}
}
#endif
@ -315,7 +357,7 @@ void KernelMainThread()
#ifdef DEBUG
/* TODO: This should not be enabled because it may cause a deadlock. Not sure where or how. */
// Tasking::PCB *tskMgr = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Debug Task Manager", Tasking::TaskTrustLevel::Kernel);
// TaskManager->CreateThread(tskMgr, (Tasking::IP)TaskMgr)->SetPriority(Tasking::High);
// TaskManager->CreateThread(tskMgr, (Tasking::IP)TaskMgr)->SetPriority(Tasking::Low);
TreeFS(vfs->GetRootNode(), 0);
#endif

View File

@ -28,13 +28,26 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
CPU::Interrupts(CPU::Enable);
SmartLock(SyscallsLock); /* TODO: This should be replaced or moved somewhere else. */
#if defined(a64)
switch (TaskManager->GetCurrentThread()->Info.Compatibility)
Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info;
Tasking::TaskInfo *Ttinfo = &TaskManager->GetCurrentThread()->Info;
uint64_t TempTimeCalc = TimeManager->GetCounter();
switch (Ttinfo->Compatibility)
{
case Tasking::TaskCompatibility::Native:
return HandleNativeSyscalls(Frame);
{
uintptr_t ret = HandleNativeSyscalls(Frame);
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
return ret;
}
case Tasking::TaskCompatibility::Linux:
return HandleLinuxSyscalls(Frame);
{
uintptr_t ret = HandleLinuxSyscalls(Frame);
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
return ret;
}
case Tasking::TaskCompatibility::Windows:
{
error("Windows compatibility not implemented yet.");
@ -47,10 +60,5 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
break;
}
}
#elif defined(a32)
fixme("System call %lld", Frame->eax);
#elif defined(aa64)
fixme("System call");
#endif
return -1;
assert(false); /* Should never reach here. */
}

View File

@ -476,8 +476,9 @@ namespace Tasking
warn("Scheduler stopped.");
return;
}
bool ProcessNotChanged = false;
CPU::x64::writecr3({.raw = (uint64_t)KernelPageTable}); /* Restore kernel page table for safety reasons. */
uint64_t SchedTmpTicks = CPU::Counter();
uint64_t SchedTmpTicks = TimeManager->GetCounter();
this->LastTaskTicks.store(SchedTmpTicks - this->SchedulerTicks.load());
CPUData *CurrentCPU = GetCurrentCPU();
schedbg("Scheduler called on CPU %d.", CurrentCPU->ID);
@ -511,6 +512,7 @@ namespace Tasking
if (unlikely(InvalidPCB(CurrentCPU->CurrentProcess.load()) || InvalidTCB(CurrentCPU->CurrentThread.load())))
{
schedbg("Invalid process or thread. Finding a new one.");
ProcessNotChanged = true;
if (this->FindNewProcess(CurrentCPU))
goto Success;
else
@ -539,6 +541,7 @@ namespace Tasking
#ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER
SuccessSource = 1;
#endif
ProcessNotChanged = true;
goto Success;
}
schedbg("Passed GetNextAvailableThread");
@ -567,22 +570,24 @@ namespace Tasking
}
}
/* [this]->RealEnd */
warn("Unwanted reach!");
TaskingScheduler_OneShot(100);
goto RealEnd;
goto End;
/* Idle-->Success */
Idle:
ProcessNotChanged = true;
CurrentCPU->CurrentProcess = IdleProcess;
CurrentCPU->CurrentThread = IdleThread;
/* Success-->End */
Success:
schedbg("Process \"%s\"(%d) Thread \"%s\"(%d) is now running on CPU %d",
CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID,
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID);
if (!ProcessNotChanged)
UpdateUsage(&CurrentCPU->CurrentProcess->Info, &CurrentCPU->CurrentProcess->Security, CurrentCPU->ID);
UpdateUsage(&CurrentCPU->CurrentThread->Info, &CurrentCPU->CurrentThread->Security, CurrentCPU->ID);
CurrentCPU->CurrentProcess->Status = TaskStatus::Running;
CurrentCPU->CurrentThread->Status = TaskStatus::Running;
@ -621,21 +626,9 @@ namespace Tasking
break;
}
/* End-->RealEnd */
// End:
/* TODO: This is not accurate. */
if (CurrentCPU->CurrentProcess->Security.TrustLevel == TaskTrustLevel::User)
UpdateUserTime(&CurrentCPU->CurrentProcess->Info);
else
UpdateKernelTime(&CurrentCPU->CurrentProcess->Info);
if (CurrentCPU->CurrentThread->Security.TrustLevel == TaskTrustLevel::User)
UpdateUserTime(&CurrentCPU->CurrentThread->Info);
else
UpdateKernelTime(&CurrentCPU->CurrentThread->Info);
UpdateUsage(&CurrentCPU->CurrentProcess->Info, CurrentCPU->ID);
UpdateUsage(&CurrentCPU->CurrentThread->Info, CurrentCPU->ID);
if (!ProcessNotChanged)
(&CurrentCPU->CurrentProcess->Info)->LastUpdateTime = TimeManager->GetCounter();
(&CurrentCPU->CurrentThread->Info)->LastUpdateTime = TimeManager->GetCounter();
TaskingScheduler_OneShot(CurrentCPU->CurrentThread->Info.Priority);
if (CurrentCPU->CurrentThread->Security.IsDebugEnabled && CurrentCPU->CurrentThread->Security.IsKernelDebugEnabled)
@ -666,9 +659,8 @@ namespace Tasking
Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode);
schedbg("================================================================");
/* RealEnd->[Function Exit] */
RealEnd:
this->SchedulerTicks.store(CPU::Counter() - SchedTmpTicks);
End:
this->SchedulerTicks.store(TimeManager->GetCounter() - SchedTmpTicks);
__sync; /* TODO: Is this really needed? */
}

View File

@ -172,40 +172,16 @@ namespace Tasking
}
}
SafeFunction NIF void Task::UpdateUserTime(TaskInfo *Info)
SafeFunction NIF void Task::UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core)
{
// TODO
Info->UserTime++;
}
uint64_t CurrentTime = TimeManager->GetCounter();
uint64_t TimePassed = CurrentTime - Info->LastUpdateTime;
// Info->LastUpdateTime = CurrentTime;
SafeFunction NIF void Task::UpdateKernelTime(TaskInfo *Info)
{
// TODO
Info->KernelTime++;
}
SafeFunction NIF void Task::UpdateUsage(TaskInfo *Info, int Core)
{
if (Info->Affinity[Core] == true)
{
// TODO: Not working(?)
uint64_t CounterNow = CPU::Counter();
Info->OldUserTime = Info->CurrentUserTime;
Info->OldKernelTime = Info->CurrentKernelTime;
Info->CurrentUserTime = Info->UserTime;
Info->CurrentKernelTime = Info->KernelTime;
Info->Usage[Core] = (Info->CurrentUserTime - Info->OldUserTime) + (Info->CurrentKernelTime - Info->OldKernelTime);
Info->Usage[Core] = (Info->Usage[Core] * 100) / (CounterNow - Info->SpawnTime);
Info->OldUserTime = Info->CurrentUserTime;
Info->OldKernelTime = Info->CurrentKernelTime;
Info->CurrentUserTime = Info->UserTime;
Info->CurrentKernelTime = Info->KernelTime;
}
if (Security->TrustLevel == TaskTrustLevel::User)
Info->UserTime += TimePassed;
else
Info->KernelTime += TimePassed;
}
void ThreadDoExit()
@ -635,7 +611,7 @@ namespace Tasking
}
Thread->Info = {};
Thread->Info.SpawnTime = CPU::Counter();
Thread->Info.SpawnTime = TimeManager->GetCounter();
Thread->Info.Year = 0;
Thread->Info.Month = 0;
Thread->Info.Day = 0;
@ -644,7 +620,6 @@ namespace Tasking
Thread->Info.Second = 0;
for (int i = 0; i < MAX_CPU; i++)
{
Thread->Info.Usage[i] = 0;
Thread->Info.Affinity[i] = true;
}
Thread->Info.Priority = TaskPriority::Normal;
@ -741,7 +716,7 @@ namespace Tasking
}
Process->Info = {};
Process->Info.SpawnTime = CPU::Counter();
Process->Info.SpawnTime = TimeManager->GetCounter();
Process->Info.Year = 0;
Process->Info.Month = 0;
Process->Info.Day = 0;
@ -750,7 +725,6 @@ namespace Tasking
Process->Info.Second = 0;
for (int i = 0; i < MAX_CPU; i++)
{
Process->Info.Usage[i] = 0;
Process->Info.Affinity[i] = true;
}
Process->Info.Priority = TaskPriority::Normal;

View File

@ -95,13 +95,12 @@ namespace Tasking
struct TaskInfo
{
uint64_t OldUserTime = 0;
uint64_t OldKernelTime = 0;
uint64_t SleepUntil = 0;
uint64_t SpawnTime = 0;
uint64_t OldUserTime = 0, CurrentUserTime = 0;
uint64_t OldKernelTime = 0, CurrentKernelTime = 0;
uint64_t KernelTime = 0, UserTime = 0;
uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0;
uint64_t Year, Month, Day, Hour, Minute, Second;
uint64_t Usage[256]; // MAX_CPU
bool Affinity[256]; // MAX_CPU
TaskPriority Priority;
TaskArchitecture Architecture;
@ -252,9 +251,7 @@ namespace Tasking
void RemoveThread(TCB *tcb);
void RemoveProcess(PCB *pcb);
void UpdateUserTime(TaskInfo *Info);
void UpdateKernelTime(TaskInfo *Info);
void UpdateUsage(TaskInfo *Info, int Core);
void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core);
bool FindNewProcess(void *CPUDataPointer);
bool GetNextAvailableThread(void *CPUDataPointer);
@ -287,14 +284,6 @@ namespace Tasking
void RevertProcessCreation(PCB *Process);
void RevertThreadCreation(TCB *Thread);
long GetUsage(int Core)
{
if (IdleProcess)
return 100 - IdleProcess->Info.Usage[Core];
else
return 0;
}
void KillThread(TCB *tcb, int Code)
{
tcb->Status = TaskStatus::Terminated;