From 198e6d7cf62cf90c5d2563fa1b9db7793996ef27 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 4 Aug 2023 10:22:20 +0300 Subject: [PATCH] Kernel: Start work on abstracting Timers --- kernel/CMakeLists.txt | 5 +-- kernel/arch/x86_64/IDT.cpp | 1 + kernel/include/kernel/Debug.h | 16 ++++----- kernel/include/kernel/PIT.h | 14 -------- kernel/include/kernel/Timer/PIT.h | 23 ++++++++++++ kernel/include/kernel/Timer/Timer.h | 36 +++++++++++++++++++ kernel/kernel/Debug.cpp | 6 ++++ kernel/kernel/FS/DevFS/FileSystem.cpp | 3 +- kernel/kernel/Input/PS2Controller.cpp | 9 ++--- kernel/kernel/Process.cpp | 5 +-- kernel/kernel/Scheduler.cpp | 3 +- kernel/kernel/Storage/ATABus.cpp | 9 ++--- kernel/kernel/{ => Timer}/PIT.cpp | 20 ++++++++--- kernel/kernel/Timer/Timer.cpp | 51 +++++++++++++++++++++++++++ kernel/kernel/kernel.cpp | 8 ++--- 15 files changed, 163 insertions(+), 46 deletions(-) delete mode 100644 kernel/include/kernel/PIT.h create mode 100644 kernel/include/kernel/Timer/PIT.h create mode 100644 kernel/include/kernel/Timer/Timer.h rename kernel/kernel/{ => Timer}/PIT.cpp (78%) create mode 100644 kernel/kernel/Timer/Timer.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index c9a69f5cec..9f0899ca1b 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -40,7 +40,6 @@ set(KERNEL_SOURCES kernel/Panic.cpp kernel/PCI.cpp kernel/PIC.cpp - kernel/PIT.cpp kernel/Process.cpp kernel/RTC.cpp kernel/Scheduler.cpp @@ -55,9 +54,11 @@ set(KERNEL_SOURCES kernel/Storage/StorageDevice.cpp kernel/Syscall.cpp kernel/Syscall.S - kernel/Thread.cpp kernel/Terminal/TTY.cpp kernel/Terminal/VesaTerminalDriver.cpp + kernel/Thread.cpp + kernel/Timer/PIT.cpp + kernel/Timer/Timer.cpp icxxabi.cpp ) diff --git a/kernel/arch/x86_64/IDT.cpp b/kernel/arch/x86_64/IDT.cpp index 0c27543907..72216b9a35 100644 --- a/kernel/arch/x86_64/IDT.cpp +++ b/kernel/arch/x86_64/IDT.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include diff --git a/kernel/include/kernel/Debug.h b/kernel/include/kernel/Debug.h index d34c0fca17..086f0f3714 100644 --- a/kernel/include/kernel/Debug.h +++ b/kernel/include/kernel/Debug.h @@ -1,15 +1,14 @@ #pragma once #include -#include -#define dprintln(...) \ - do { \ - Debug::DebugLock::lock(); \ - BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", PIT::ms_since_boot() / 1000, PIT::ms_since_boot() % 1000, __FILE__, __LINE__); \ - BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \ - BAN::Formatter::print(Debug::putchar, "\r\n"); \ - Debug::DebugLock::unlock(); \ +#define dprintln(...) \ + do { \ + Debug::DebugLock::lock(); \ + Debug::print_prefix(__FILE__, __LINE__); \ + BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \ + BAN::Formatter::print(Debug::putchar, "\r\n"); \ + Debug::DebugLock::unlock(); \ } while(false) #define dwarnln(...) \ @@ -36,6 +35,7 @@ namespace Debug { void dump_stack_trace(); void putchar(char); + void print_prefix(const char*, int); class DebugLock { diff --git a/kernel/include/kernel/PIT.h b/kernel/include/kernel/PIT.h deleted file mode 100644 index 0befacd9b5..0000000000 --- a/kernel/include/kernel/PIT.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -#define PIT_IRQ 0 - -namespace PIT -{ - - uint64_t ms_since_boot(); - void initialize(); - void sleep(uint64_t); - -} \ No newline at end of file diff --git a/kernel/include/kernel/Timer/PIT.h b/kernel/include/kernel/Timer/PIT.h new file mode 100644 index 0000000000..09025ccf85 --- /dev/null +++ b/kernel/include/kernel/Timer/PIT.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#define PIT_IRQ 0 + +namespace Kernel +{ + + class PIT final : public Timer + { + public: + static BAN::ErrorOr> create(); + + virtual uint64_t ms_since_boot() const override; + virtual void sleep(uint64_t) const override; + + private: + void initialize(); + }; + +} \ No newline at end of file diff --git a/kernel/include/kernel/Timer/Timer.h b/kernel/include/kernel/Timer/Timer.h new file mode 100644 index 0000000000..e72450f55b --- /dev/null +++ b/kernel/include/kernel/Timer/Timer.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class Timer + { + public: + virtual ~Timer() {}; + virtual uint64_t ms_since_boot() const = 0; + virtual void sleep(uint64_t) const = 0; + }; + + class TimerHandler + { + public: + static void initialize(); + static TimerHandler& get(); + static bool is_initialized(); + + uint64_t ms_since_boot() const; + void sleep(uint64_t) const; + + private: + TimerHandler() = default; + + void initialize_timers(); + + private: + BAN::Vector> m_timers; + }; + +} \ No newline at end of file diff --git a/kernel/kernel/Debug.cpp b/kernel/kernel/Debug.cpp index ae88f12b80..12295f96cc 100644 --- a/kernel/kernel/Debug.cpp +++ b/kernel/kernel/Debug.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace Debug { @@ -55,6 +56,11 @@ namespace Debug return Kernel::TTY::putchar_current(ch); } + void print_prefix(const char* file, int line) + { + auto ms_since_boot = Kernel::TimerHandler::is_initialized() ? Kernel::TimerHandler::get().ms_since_boot() : 0; + BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", ms_since_boot / 1000, ms_since_boot % 1000, file, line); + } static Kernel::RecursiveSpinLock s_debug_lock; diff --git a/kernel/kernel/FS/DevFS/FileSystem.cpp b/kernel/kernel/FS/DevFS/FileSystem.cpp index 5ec1db3ff6..8837fa7fed 100644 --- a/kernel/kernel/FS/DevFS/FileSystem.cpp +++ b/kernel/kernel/FS/DevFS/FileSystem.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace Kernel { @@ -45,7 +46,7 @@ namespace Kernel ); s_instance->m_device_lock.unlock(); - PIT::sleep(1); + Kernel::TimerHandler::get().sleep(1); } }, nullptr ); diff --git a/kernel/kernel/Input/PS2Controller.cpp b/kernel/kernel/Input/PS2Controller.cpp index 8a6cf088a8..1c25beb06d 100644 --- a/kernel/kernel/Input/PS2Controller.cpp +++ b/kernel/kernel/Input/PS2Controller.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Kernel::Input { @@ -107,8 +108,8 @@ namespace Kernel::Input { if (device == 1) IO::outb(PS2::IOPort::COMMAND, PS2::Command::WRITE_TO_SECOND_PORT); - uint64_t timeout = PIT::ms_since_boot() + s_device_timeout_ms; - while (PIT::ms_since_boot() < timeout) + uint64_t timeout = TimerHandler::get().ms_since_boot() + s_device_timeout_ms; + while (TimerHandler::get().ms_since_boot() < timeout) { if (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_FULL)) { @@ -121,8 +122,8 @@ namespace Kernel::Input static BAN::ErrorOr device_read_byte() { - uint64_t timeout = PIT::ms_since_boot() + s_device_timeout_ms; - while (PIT::ms_since_boot() < timeout) + uint64_t timeout = TimerHandler::get().ms_since_boot() + s_device_timeout_ms; + while (TimerHandler::get().ms_since_boot() < timeout) if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL) return IO::inb(PS2::IOPort::DATA); return BAN::Error::from_error_code(ErrorCode::PS2_Timeout); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index e1c46afbd2..0f809cea24 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -472,7 +473,7 @@ namespace Kernel BAN::ErrorOr Process::sys_sleep(int seconds) { - PIT::sleep(seconds * 1000); + TimerHandler::get().sleep(seconds * 1000); return 0; } @@ -810,7 +811,7 @@ namespace Kernel { case CLOCK_MONOTONIC: { - uint64_t time_ms = PIT::ms_since_boot(); + uint64_t time_ms = TimerHandler::get().ms_since_boot(); tp->tv_sec = time_ms / 1000; tp->tv_nsec = (time_ms % 1000) * 1000000; break; diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index fc843a9309..7985937db9 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #if 1 #define VERIFY_STI() ASSERT(interrupts_enabled()) @@ -112,7 +113,7 @@ namespace Kernel { VERIFY_CLI(); - uint64_t current_time = PIT::ms_since_boot(); + uint64_t current_time = TimerHandler::get().ms_since_boot(); while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time) { Thread* thread = m_sleeping_threads.front().thread; diff --git a/kernel/kernel/Storage/ATABus.cpp b/kernel/kernel/Storage/ATABus.cpp index fbb20c3916..094d2c0f48 100644 --- a/kernel/kernel/Storage/ATABus.cpp +++ b/kernel/kernel/Storage/ATABus.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Kernel { @@ -99,7 +100,7 @@ namespace Kernel { uint8_t device_index = this->device_index(device); io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | (device_index << 4)); - PIT::sleep(1); + TimerHandler::get().sleep(1); } ATABus::DeviceType ATABus::identify(const ATADevice& device, uint16_t* buffer) @@ -110,7 +111,7 @@ namespace Kernel io_write(ATA_PORT_CONTROL, ATA_CONTROL_nIEN); io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY); - PIT::sleep(1); + TimerHandler::get().sleep(1); // No device on port if (io_read(ATA_PORT_STATUS) == 0) @@ -134,7 +135,7 @@ namespace Kernel } io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET); - PIT::sleep(1); + TimerHandler::get().sleep(1); if (auto res = wait(true); res.is_error()) { @@ -303,7 +304,7 @@ namespace Kernel io_write(ATA_PORT_LBA2, (uint8_t)(lba >> 16)); io_write(ATA_PORT_COMMAND, ATA_COMMAND_WRITE_SECTORS); - PIT::sleep(1); + TimerHandler::get().sleep(1); for (uint32_t sector = 0; sector < sector_count; sector++) { diff --git a/kernel/kernel/PIT.cpp b/kernel/kernel/Timer/PIT.cpp similarity index 78% rename from kernel/kernel/PIT.cpp rename to kernel/kernel/Timer/PIT.cpp index 702ba6e15a..1450ae1673 100644 --- a/kernel/kernel/PIT.cpp +++ b/kernel/kernel/Timer/PIT.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #define TIMER0_CTL 0x40 #define TIMER1_CTL 0x41 @@ -20,7 +21,7 @@ #define BASE_FREQUENCY 1193182 #define TICKS_PER_SECOND 1000 -namespace PIT +namespace Kernel { static volatile uint64_t s_system_time = 0; @@ -31,12 +32,16 @@ namespace PIT Kernel::Scheduler::get().timer_reschedule(); } - uint64_t ms_since_boot() + BAN::ErrorOr> PIT::create() { - return s_system_time; + PIT* pit = new PIT; + if (pit == nullptr) + return BAN::Error::from_errno(ENOMEM); + pit->initialize(); + return BAN::UniqPtr::adopt(pit); } - void initialize() + void PIT::initialize() { constexpr uint16_t timer_reload = BASE_FREQUENCY / TICKS_PER_SECOND; @@ -50,7 +55,12 @@ namespace PIT InterruptController::get().enable_irq(PIT_IRQ); } - void sleep(uint64_t ms) + uint64_t PIT::ms_since_boot() const + { + return s_system_time; + } + + void PIT::sleep(uint64_t ms) const { if (ms == 0) return; diff --git a/kernel/kernel/Timer/Timer.cpp b/kernel/kernel/Timer/Timer.cpp new file mode 100644 index 0000000000..b5448e2764 --- /dev/null +++ b/kernel/kernel/Timer/Timer.cpp @@ -0,0 +1,51 @@ +#include +#include + +namespace Kernel +{ + + static TimerHandler* s_instance = nullptr; + + void TimerHandler::initialize() + { + ASSERT(s_instance == nullptr); + s_instance = new TimerHandler; + ASSERT(s_instance); + s_instance->initialize_timers(); + } + + TimerHandler& TimerHandler::get() + { + ASSERT(s_instance); + return *s_instance; + } + + bool TimerHandler::is_initialized() + { + return !!s_instance; + } + + void TimerHandler::initialize_timers() + { + if (auto res = PIT::create(); res.is_error()) + dwarnln("PIT: {}", res.error()); + else + { + MUST(m_timers.emplace_back(BAN::move(res.release_value()))); + dprintln("PIT initialized"); + } + + ASSERT(!m_timers.empty()); + } + + uint64_t TimerHandler::ms_since_boot() const + { + return m_timers.front()->ms_since_boot(); + } + + void TimerHandler::sleep(uint64_t ms) const + { + return m_timers.front()->sleep(ms); + } + +} \ No newline at end of file diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 2da4c5fb77..ed67feb563 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -14,15 +14,13 @@ #include #include #include -#include #include #include #include #include #include #include - -#include +#include extern "C" const char g_kernel_cmdline[]; @@ -156,8 +154,8 @@ extern "C" void kernel_main() InterruptController::initialize(cmdline.force_pic); dprintln("Interrupt controller initialized"); - PIT::initialize(); - dprintln("PIT initialized"); + TimerHandler::initialize(); + dprintln("Timers initialized"); MUST(Scheduler::initialize()); dprintln("Scheduler initialized");