mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Update timing implementation
This commit is contained in:
parent
7e201e0958
commit
89d747e52c
@ -377,7 +377,7 @@ namespace APIC
|
||||
this->lapic->Write(APIC_TDCR, Divider);
|
||||
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
|
||||
|
||||
TimeManager->Sleep(1);
|
||||
TimeManager->Sleep(1, Time::Units::Milliseconds);
|
||||
|
||||
// Mask the timer
|
||||
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
|
||||
|
@ -144,7 +144,7 @@ void DriverSleep(unsigned long Milliseconds)
|
||||
if (TaskManager)
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
else
|
||||
TimeManager->Sleep(Milliseconds);
|
||||
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
|
||||
}
|
||||
|
||||
int Driversprintf(char *Buffer, const char *Format, ...)
|
||||
|
@ -187,7 +187,7 @@ Retry:
|
||||
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
||||
{
|
||||
if (Target.load() == 0)
|
||||
Target.store(TimeManager->CalculateTarget(Timeout));
|
||||
Target.store(TimeManager->CalculateTarget(Timeout, Time::Units::Milliseconds));
|
||||
TimeoutDeadLock(LockData, Target.load());
|
||||
goto Retry;
|
||||
}
|
||||
|
77
Core/Time/HighPrecisionEventTimer.cpp
Normal file
77
Core/Time/HighPrecisionEventTimer.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <time.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../Architecture/amd64/acpi.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace Time
|
||||
{
|
||||
bool HighPrecisionEventTimer::Sleep(uint64_t Duration, Units Unit)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::GetCounter()
|
||||
{
|
||||
#if defined(a86)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
|
||||
{
|
||||
#if defined(a86)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
#endif
|
||||
}
|
||||
|
||||
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
|
||||
{
|
||||
#if defined(a86)
|
||||
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
|
||||
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
|
||||
(void *)HPET_HDR->Address.Address,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||
this->hpet = (HPET *)HPET_HDR->Address.Address;
|
||||
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
|
||||
clk = s_cst(uint32_t, this->hpet->GeneralCapabilities >> 32);
|
||||
mmoutq(&this->hpet->GeneralConfiguration, 0);
|
||||
mmoutq(&this->hpet->MainCounterValue, 0);
|
||||
mmoutq(&this->hpet->GeneralConfiguration, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
HighPrecisionEventTimer::~HighPrecisionEventTimer()
|
||||
{
|
||||
}
|
||||
}
|
148
Core/Time/Timer.cpp
Normal file
148
Core/Time/Timer.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <time.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../Architecture/amd64/acpi.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace Time
|
||||
{
|
||||
bool time::Sleep(uint64_t Duration, Units Unit)
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
case NONE:
|
||||
error("No timer is active");
|
||||
return false;
|
||||
case RTC:
|
||||
fixme("RTC sleep not implemented");
|
||||
return false;
|
||||
case PIT:
|
||||
fixme("PIT sleep not implemented");
|
||||
return false;
|
||||
case HPET:
|
||||
return hpet->Sleep(Duration, Unit);
|
||||
case ACPI:
|
||||
fixme("ACPI sleep not implemented");
|
||||
return false;
|
||||
case APIC:
|
||||
fixme("APIC sleep not implemented");
|
||||
return false;
|
||||
case TSC:
|
||||
fixme("TSC sleep not implemented");
|
||||
return false;
|
||||
default:
|
||||
error("Unknown timer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time::GetCounter()
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
case NONE:
|
||||
error("No timer is active");
|
||||
return false;
|
||||
case RTC:
|
||||
fixme("RTC sleep not implemented");
|
||||
return false;
|
||||
case PIT:
|
||||
fixme("PIT sleep not implemented");
|
||||
return false;
|
||||
case HPET:
|
||||
return hpet->GetCounter();
|
||||
case ACPI:
|
||||
fixme("ACPI sleep not implemented");
|
||||
return false;
|
||||
case APIC:
|
||||
fixme("APIC sleep not implemented");
|
||||
return false;
|
||||
case TSC:
|
||||
fixme("TSC sleep not implemented");
|
||||
return false;
|
||||
default:
|
||||
error("Unknown timer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t time::CalculateTarget(uint64_t Target, Units Unit)
|
||||
{
|
||||
switch (ActiveTimer)
|
||||
{
|
||||
case NONE:
|
||||
error("No timer is active");
|
||||
return false;
|
||||
case RTC:
|
||||
fixme("RTC sleep not implemented");
|
||||
return false;
|
||||
case PIT:
|
||||
fixme("PIT sleep not implemented");
|
||||
return false;
|
||||
case HPET:
|
||||
return hpet->CalculateTarget(Target, Unit);
|
||||
case ACPI:
|
||||
fixme("ACPI sleep not implemented");
|
||||
return false;
|
||||
case APIC:
|
||||
fixme("APIC sleep not implemented");
|
||||
return false;
|
||||
case TSC:
|
||||
fixme("TSC sleep not implemented");
|
||||
return false;
|
||||
default:
|
||||
error("Unknown timer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
time::time(void *acpi)
|
||||
{
|
||||
/* TODO: RTC check */
|
||||
/* TODO: PIT check */
|
||||
|
||||
if (acpi)
|
||||
{
|
||||
if (((ACPI::ACPI *)acpi)->HPET)
|
||||
{
|
||||
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
|
||||
ActiveTimer = HPET;
|
||||
}
|
||||
|
||||
/* TODO: ACPI check */
|
||||
/* TODO: APIC check */
|
||||
}
|
||||
|
||||
/* TODO: TSC check */
|
||||
}
|
||||
|
||||
time::~time()
|
||||
{
|
||||
debug("Destructor called");
|
||||
}
|
||||
}
|
106
Core/Timer.cpp
106
Core/Timer.cpp
@ -1,106 +0,0 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <time.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../Architecture/amd64/acpi.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace Time
|
||||
{
|
||||
void time::Sleep(uint64_t Milliseconds)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
|
||||
#ifdef DEBUG
|
||||
uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
while (Counter < Target)
|
||||
{
|
||||
Counter = mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
CPU::Pause();
|
||||
}
|
||||
#else
|
||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
#endif
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t time::GetCounter()
|
||||
{
|
||||
#if defined(a86)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t time::CalculateTarget(uint64_t Milliseconds)
|
||||
{
|
||||
#if defined(a86)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
time::time(void *_acpi)
|
||||
{
|
||||
if (_acpi)
|
||||
{
|
||||
#if defined(a64)
|
||||
this->acpi = _acpi;
|
||||
ACPI::ACPI *acpi = (ACPI::ACPI *)this->acpi;
|
||||
if (acpi->HPET)
|
||||
{
|
||||
Memory::Virtual().Remap((void *)acpi->HPET->Address.Address,
|
||||
(void *)acpi->HPET->Address.Address,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||
this->hpet = (void *)acpi->HPET->Address.Address;
|
||||
HPET *hpet = (HPET *)this->hpet;
|
||||
trace("%s timer is at address %016p", acpi->HPET->Header.OEMID, (void *)acpi->HPET->Address.Address);
|
||||
clk = s_cst(uint32_t, hpet->GeneralCapabilities >> 32);
|
||||
mmoutq(&hpet->GeneralConfiguration, 0);
|
||||
mmoutq(&hpet->MainCounterValue, 0);
|
||||
mmoutq(&hpet->GeneralConfiguration, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For now, we need HPET.
|
||||
error("HPET not found");
|
||||
KPrint("\eFF2200HPET not found");
|
||||
CPU::Stop();
|
||||
}
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
time::~time()
|
||||
{
|
||||
debug("Destructor called");
|
||||
}
|
||||
}
|
@ -52,7 +52,7 @@ namespace Execute
|
||||
{
|
||||
if (Lib.RefCount > 0)
|
||||
{
|
||||
Lib.Timeout = TimeManager->CalculateTarget(600000);
|
||||
Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
||||
debug("Reset timeout for %s", Lib.Identifier);
|
||||
continue;
|
||||
}
|
||||
@ -86,7 +86,7 @@ namespace Execute
|
||||
}
|
||||
|
||||
strcpy(sl.Identifier, Identifier);
|
||||
sl.Timeout = TimeManager->CalculateTarget(600000); /* 10 minutes */
|
||||
sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes);
|
||||
sl.RefCount = 0;
|
||||
|
||||
void *LibFile = mem->RequestPages(TO_PAGES(Length + 1), true);
|
||||
|
@ -288,7 +288,7 @@ namespace Tasking
|
||||
thread->Status = TaskStatus::Sleeping;
|
||||
if (thread->Parent->Threads.size() == 1)
|
||||
thread->Parent->Status = TaskStatus::Sleeping;
|
||||
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds);
|
||||
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds, Time::Units::Milliseconds);
|
||||
tskdbg("Thread \"%s\"(%d) is going to sleep until %llu", thread->Name, thread->ID, thread->Info.SleepUntil);
|
||||
// TaskingScheduler_OneShot(1);
|
||||
// IRQ16
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define __FENNIX_KERNEL_TIME_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <debug.h>
|
||||
|
||||
namespace Time
|
||||
{
|
||||
@ -31,7 +32,22 @@ namespace Time
|
||||
Clock ReadClock();
|
||||
Clock ConvertFromUnix(int Timestamp);
|
||||
|
||||
class time
|
||||
enum Units
|
||||
{
|
||||
Femtoseconds,
|
||||
Picoseconds,
|
||||
Nanoseconds,
|
||||
Microseconds,
|
||||
Milliseconds,
|
||||
Seconds,
|
||||
Minutes,
|
||||
Hours,
|
||||
Days,
|
||||
Months,
|
||||
Years
|
||||
};
|
||||
|
||||
class HighPrecisionEventTimer
|
||||
{
|
||||
private:
|
||||
struct HPET
|
||||
@ -47,14 +63,70 @@ namespace Time
|
||||
uint64_t Reserved4;
|
||||
};
|
||||
|
||||
void *acpi;
|
||||
void *hpet;
|
||||
uint32_t clk = 0;
|
||||
HPET *hpet;
|
||||
|
||||
uint64_t ConvertUnit(Units Unit)
|
||||
{
|
||||
switch (Unit)
|
||||
{
|
||||
case Femtoseconds:
|
||||
return 1;
|
||||
case Picoseconds:
|
||||
return 1000;
|
||||
case Nanoseconds:
|
||||
return 1000000;
|
||||
case Microseconds:
|
||||
return 1000000000;
|
||||
case Milliseconds:
|
||||
return 1000000000000;
|
||||
case Seconds:
|
||||
return 1000000000000000;
|
||||
case Minutes:
|
||||
return 1000000000000000000;
|
||||
// case Hours:
|
||||
// return 1000000000000000000000;
|
||||
// case Days:
|
||||
// return 1000000000000000000000000;
|
||||
// case Months:
|
||||
// return 1000000000000000000000000000;
|
||||
// case Years:
|
||||
// return 1000000000000000000000000000000;
|
||||
default:
|
||||
error("Invalid time unit %d", Unit);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void Sleep(uint64_t Milliseconds);
|
||||
bool Sleep(uint64_t Duration, Units Unit);
|
||||
uint64_t GetCounter();
|
||||
uint64_t CalculateTarget(uint64_t Milliseconds);
|
||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
||||
|
||||
HighPrecisionEventTimer(void *hpet);
|
||||
~HighPrecisionEventTimer();
|
||||
};
|
||||
|
||||
class time
|
||||
{
|
||||
private:
|
||||
enum _ActiveTimer
|
||||
{
|
||||
NONE,
|
||||
RTC,
|
||||
PIT,
|
||||
HPET,
|
||||
ACPI,
|
||||
APIC,
|
||||
TSC,
|
||||
} ActiveTimer = NONE;
|
||||
|
||||
HighPrecisionEventTimer *hpet;
|
||||
|
||||
public:
|
||||
bool Sleep(uint64_t Duration, Units Unit);
|
||||
uint64_t GetCounter();
|
||||
uint64_t CalculateTarget(uint64_t Target, Units Unit);
|
||||
time(void *acpi);
|
||||
~time();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user