forked from Bananymous/banan-os
Kernel: Start work on abstracting Timers
This commit is contained in:
parent
07ee898f4f
commit
198e6d7cf6
|
@ -40,7 +40,6 @@ set(KERNEL_SOURCES
|
||||||
kernel/Panic.cpp
|
kernel/Panic.cpp
|
||||||
kernel/PCI.cpp
|
kernel/PCI.cpp
|
||||||
kernel/PIC.cpp
|
kernel/PIC.cpp
|
||||||
kernel/PIT.cpp
|
|
||||||
kernel/Process.cpp
|
kernel/Process.cpp
|
||||||
kernel/RTC.cpp
|
kernel/RTC.cpp
|
||||||
kernel/Scheduler.cpp
|
kernel/Scheduler.cpp
|
||||||
|
@ -55,9 +54,11 @@ set(KERNEL_SOURCES
|
||||||
kernel/Storage/StorageDevice.cpp
|
kernel/Storage/StorageDevice.cpp
|
||||||
kernel/Syscall.cpp
|
kernel/Syscall.cpp
|
||||||
kernel/Syscall.S
|
kernel/Syscall.S
|
||||||
kernel/Thread.cpp
|
|
||||||
kernel/Terminal/TTY.cpp
|
kernel/Terminal/TTY.cpp
|
||||||
kernel/Terminal/VesaTerminalDriver.cpp
|
kernel/Terminal/VesaTerminalDriver.cpp
|
||||||
|
kernel/Thread.cpp
|
||||||
|
kernel/Timer/PIT.cpp
|
||||||
|
kernel/Timer/Timer.cpp
|
||||||
icxxabi.cpp
|
icxxabi.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <kernel/Panic.h>
|
#include <kernel/Panic.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Formatter.h>
|
#include <BAN/Formatter.h>
|
||||||
#include <kernel/PIT.h>
|
|
||||||
|
|
||||||
#define dprintln(...) \
|
#define dprintln(...) \
|
||||||
do { \
|
do { \
|
||||||
Debug::DebugLock::lock(); \
|
Debug::DebugLock::lock(); \
|
||||||
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", PIT::ms_since_boot() / 1000, PIT::ms_since_boot() % 1000, __FILE__, __LINE__); \
|
Debug::print_prefix(__FILE__, __LINE__); \
|
||||||
BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \
|
BAN::Formatter::print(Debug::putchar, __VA_ARGS__); \
|
||||||
BAN::Formatter::print(Debug::putchar, "\r\n"); \
|
BAN::Formatter::print(Debug::putchar, "\r\n"); \
|
||||||
Debug::DebugLock::unlock(); \
|
Debug::DebugLock::unlock(); \
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
#define dwarnln(...) \
|
#define dwarnln(...) \
|
||||||
|
@ -36,6 +35,7 @@ namespace Debug
|
||||||
{
|
{
|
||||||
void dump_stack_trace();
|
void dump_stack_trace();
|
||||||
void putchar(char);
|
void putchar(char);
|
||||||
|
void print_prefix(const char*, int);
|
||||||
|
|
||||||
class DebugLock
|
class DebugLock
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define PIT_IRQ 0
|
|
||||||
|
|
||||||
namespace PIT
|
|
||||||
{
|
|
||||||
|
|
||||||
uint64_t ms_since_boot();
|
|
||||||
void initialize();
|
|
||||||
void sleep(uint64_t);
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PIT_IRQ 0
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class PIT final : public Timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::UniqPtr<PIT>> create();
|
||||||
|
|
||||||
|
virtual uint64_t ms_since_boot() const override;
|
||||||
|
virtual void sleep(uint64_t) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/UniqPtr.h>
|
||||||
|
#include <BAN/Vector.h>
|
||||||
|
|
||||||
|
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<BAN::UniqPtr<Timer>> m_timers;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
#include <kernel/Serial.h>
|
#include <kernel/Serial.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Debug
|
namespace Debug
|
||||||
{
|
{
|
||||||
|
@ -55,6 +56,11 @@ namespace Debug
|
||||||
return Kernel::TTY::putchar_current(ch);
|
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;
|
static Kernel::RecursiveSpinLock s_debug_lock;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <kernel/FS/RamFS/Inode.h>
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -45,7 +46,7 @@ namespace Kernel
|
||||||
);
|
);
|
||||||
s_instance->m_device_lock.unlock();
|
s_instance->m_device_lock.unlock();
|
||||||
|
|
||||||
PIT::sleep(1);
|
Kernel::TimerHandler::get().sleep(1);
|
||||||
}
|
}
|
||||||
}, nullptr
|
}, nullptr
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <kernel/Input/PS2Keyboard.h>
|
#include <kernel/Input/PS2Keyboard.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
@ -107,8 +108,8 @@ namespace Kernel::Input
|
||||||
{
|
{
|
||||||
if (device == 1)
|
if (device == 1)
|
||||||
IO::outb(PS2::IOPort::COMMAND, PS2::Command::WRITE_TO_SECOND_PORT);
|
IO::outb(PS2::IOPort::COMMAND, PS2::Command::WRITE_TO_SECOND_PORT);
|
||||||
uint64_t timeout = PIT::ms_since_boot() + s_device_timeout_ms;
|
uint64_t timeout = TimerHandler::get().ms_since_boot() + s_device_timeout_ms;
|
||||||
while (PIT::ms_since_boot() < timeout)
|
while (TimerHandler::get().ms_since_boot() < timeout)
|
||||||
{
|
{
|
||||||
if (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_FULL))
|
if (!(IO::inb(PS2::IOPort::STATUS) & PS2::Status::INPUT_FULL))
|
||||||
{
|
{
|
||||||
|
@ -121,8 +122,8 @@ namespace Kernel::Input
|
||||||
|
|
||||||
static BAN::ErrorOr<uint8_t> device_read_byte()
|
static BAN::ErrorOr<uint8_t> device_read_byte()
|
||||||
{
|
{
|
||||||
uint64_t timeout = PIT::ms_since_boot() + s_device_timeout_ms;
|
uint64_t timeout = TimerHandler::get().ms_since_boot() + s_device_timeout_ms;
|
||||||
while (PIT::ms_since_boot() < timeout)
|
while (TimerHandler::get().ms_since_boot() < timeout)
|
||||||
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL)
|
if (IO::inb(PS2::IOPort::STATUS) & PS2::Status::OUTPUT_FULL)
|
||||||
return IO::inb(PS2::IOPort::DATA);
|
return IO::inb(PS2::IOPort::DATA);
|
||||||
return BAN::Error::from_error_code(ErrorCode::PS2_Timeout);
|
return BAN::Error::from_error_code(ErrorCode::PS2_Timeout);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <kernel/Memory/PageTableScope.h>
|
#include <kernel/Memory/PageTableScope.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
#include <LibELF/ELF.h>
|
#include <LibELF/ELF.h>
|
||||||
#include <LibELF/Values.h>
|
#include <LibELF/Values.h>
|
||||||
|
|
||||||
|
@ -472,7 +473,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
||||||
{
|
{
|
||||||
PIT::sleep(seconds * 1000);
|
TimerHandler::get().sleep(seconds * 1000);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +811,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
case CLOCK_MONOTONIC:
|
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_sec = time_ms / 1000;
|
||||||
tp->tv_nsec = (time_ms % 1000) * 1000000;
|
tp->tv_nsec = (time_ms % 1000) * 1000000;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define VERIFY_STI() ASSERT(interrupts_enabled())
|
#define VERIFY_STI() ASSERT(interrupts_enabled())
|
||||||
|
@ -112,7 +113,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
VERIFY_CLI();
|
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)
|
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
|
||||||
{
|
{
|
||||||
Thread* thread = m_sleeping_threads.front().thread;
|
Thread* thread = m_sleeping_threads.front().thread;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <kernel/Storage/ATADevice.h>
|
#include <kernel/Storage/ATADevice.h>
|
||||||
#include <kernel/Storage/ATABus.h>
|
#include <kernel/Storage/ATABus.h>
|
||||||
#include <kernel/Storage/ATADefinitions.h>
|
#include <kernel/Storage/ATADefinitions.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -99,7 +100,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
uint8_t device_index = this->device_index(device);
|
uint8_t device_index = this->device_index(device);
|
||||||
io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | (device_index << 4));
|
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)
|
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_CONTROL, ATA_CONTROL_nIEN);
|
||||||
|
|
||||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY);
|
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY);
|
||||||
PIT::sleep(1);
|
TimerHandler::get().sleep(1);
|
||||||
|
|
||||||
// No device on port
|
// No device on port
|
||||||
if (io_read(ATA_PORT_STATUS) == 0)
|
if (io_read(ATA_PORT_STATUS) == 0)
|
||||||
|
@ -134,7 +135,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
|
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
|
||||||
PIT::sleep(1);
|
TimerHandler::get().sleep(1);
|
||||||
|
|
||||||
if (auto res = wait(true); res.is_error())
|
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_LBA2, (uint8_t)(lba >> 16));
|
||||||
io_write(ATA_PORT_COMMAND, ATA_COMMAND_WRITE_SECTORS);
|
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++)
|
for (uint32_t sector = 0; sector < sector_count; sector++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
#define TIMER0_CTL 0x40
|
#define TIMER0_CTL 0x40
|
||||||
#define TIMER1_CTL 0x41
|
#define TIMER1_CTL 0x41
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
#define BASE_FREQUENCY 1193182
|
#define BASE_FREQUENCY 1193182
|
||||||
#define TICKS_PER_SECOND 1000
|
#define TICKS_PER_SECOND 1000
|
||||||
|
|
||||||
namespace PIT
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
static volatile uint64_t s_system_time = 0;
|
static volatile uint64_t s_system_time = 0;
|
||||||
|
@ -31,12 +32,16 @@ namespace PIT
|
||||||
Kernel::Scheduler::get().timer_reschedule();
|
Kernel::Scheduler::get().timer_reschedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ms_since_boot()
|
BAN::ErrorOr<BAN::UniqPtr<PIT>> PIT::create()
|
||||||
{
|
{
|
||||||
return s_system_time;
|
PIT* pit = new PIT;
|
||||||
|
if (pit == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
pit->initialize();
|
||||||
|
return BAN::UniqPtr<PIT>::adopt(pit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize()
|
void PIT::initialize()
|
||||||
{
|
{
|
||||||
constexpr uint16_t timer_reload = BASE_FREQUENCY / TICKS_PER_SECOND;
|
constexpr uint16_t timer_reload = BASE_FREQUENCY / TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
@ -50,7 +55,12 @@ namespace PIT
|
||||||
InterruptController::get().enable_irq(PIT_IRQ);
|
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)
|
if (ms == 0)
|
||||||
return;
|
return;
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
#include <kernel/Timer/PIT.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,15 +14,13 @@
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
#include <kernel/PIC.h>
|
#include <kernel/PIC.h>
|
||||||
#include <kernel/PIT.h>
|
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Serial.h>
|
#include <kernel/Serial.h>
|
||||||
#include <kernel/Syscall.h>
|
#include <kernel/Syscall.h>
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Terminal/VesaTerminalDriver.h>
|
#include <kernel/Terminal/VesaTerminalDriver.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
#include <LibELF/ELF.h>
|
|
||||||
|
|
||||||
extern "C" const char g_kernel_cmdline[];
|
extern "C" const char g_kernel_cmdline[];
|
||||||
|
|
||||||
|
@ -156,8 +154,8 @@ extern "C" void kernel_main()
|
||||||
InterruptController::initialize(cmdline.force_pic);
|
InterruptController::initialize(cmdline.force_pic);
|
||||||
dprintln("Interrupt controller initialized");
|
dprintln("Interrupt controller initialized");
|
||||||
|
|
||||||
PIT::initialize();
|
TimerHandler::initialize();
|
||||||
dprintln("PIT initialized");
|
dprintln("Timers initialized");
|
||||||
|
|
||||||
MUST(Scheduler::initialize());
|
MUST(Scheduler::initialize());
|
||||||
dprintln("Scheduler initialized");
|
dprintln("Scheduler initialized");
|
||||||
|
|
Loading…
Reference in New Issue