Serenity Operating System
at master 123 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Error.h> 10#include <AK/OwnPtr.h> 11#include <AK/Platform.h> 12#include <AK/Time.h> 13#include <AK/Types.h> 14#include <AK/Vector.h> 15#include <Kernel/API/TimePage.h> 16#include <Kernel/Arch/RegisterState.h> 17#include <Kernel/Forward.h> 18#include <Kernel/Library/LockRefPtr.h> 19#include <Kernel/UnixTypes.h> 20 21namespace Kernel { 22 23#define OPTIMAL_TICKS_PER_SECOND_RATE 250 24#define OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE 1000 25 26class HardwareTimerBase; 27 28enum class TimePrecision { 29 Coarse = 0, 30 Precise 31}; 32 33class TimeManagement { 34 35public: 36 TimeManagement(); 37 static void initialize(u32 cpu); 38 static bool is_initialized(); 39 static TimeManagement& the(); 40 41 static u64 scheduler_current_time(); 42 43 static ErrorOr<void> validate_clock_id(clockid_t); 44 Time current_time(clockid_t) const; 45 Time monotonic_time(TimePrecision = TimePrecision::Coarse) const; 46 Time monotonic_time_raw() const 47 { 48 // TODO: implement 49 return monotonic_time(TimePrecision::Precise); 50 } 51 Time epoch_time(TimePrecision = TimePrecision::Precise) const; 52 void set_epoch_time(Time); 53 time_t ticks_per_second() const; 54 static Time boot_time(); 55 Time clock_resolution() const; 56 57 bool is_system_timer(HardwareTimerBase const&) const; 58 59 void increment_time_since_boot(); 60 61 static bool is_hpet_periodic_mode_allowed(); 62 63 bool enable_profile_timer(); 64 bool disable_profile_timer(); 65 66 u64 uptime_ms() const; 67 static Time now(); 68 69 // FIXME: Should use AK::Time internally 70 // FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates. 71 timespec remaining_epoch_time_adjustment() const { return m_remaining_epoch_time_adjustment; } 72 // FIXME: Should use AK::Time internally 73 // FIXME: Also, most likely broken, because it does not check m_update[12] for in-progress updates. 74 void set_remaining_epoch_time_adjustment(timespec const& adjustment) { m_remaining_epoch_time_adjustment = adjustment; } 75 76 bool can_query_precise_time() const { return m_can_query_precise_time; } 77 78 Memory::VMObject& time_page_vmobject(); 79 80private: 81 TimePage& time_page(); 82 void update_time_page(); 83 84#if ARCH(X86_64) 85 bool probe_and_set_x86_legacy_hardware_timers(); 86 bool probe_and_set_x86_non_legacy_hardware_timers(); 87 void increment_time_since_boot_hpet(); 88 static void update_time(RegisterState const&); 89#elif ARCH(AARCH64) 90 bool probe_and_set_aarch64_hardware_timers(); 91#else 92# error Unknown architecture 93#endif 94 Vector<HardwareTimerBase*> scan_and_initialize_periodic_timers(); 95 Vector<HardwareTimerBase*> scan_for_non_periodic_timers(); 96 Vector<NonnullLockRefPtr<HardwareTimerBase>> m_hardware_timers; 97 void set_system_timer(HardwareTimerBase&); 98 static void system_timer_tick(RegisterState const&); 99 100 // Variables between m_update1 and m_update2 are synchronized 101 // FIXME: Replace m_update1 and m_update2 with a SpinlockLocker 102 Atomic<u32> m_update1 { 0 }; 103 u32 m_ticks_this_second { 0 }; 104 u64 m_seconds_since_boot { 0 }; 105 // FIXME: Should use AK::Time internally 106 timespec m_epoch_time { 0, 0 }; 107 timespec m_remaining_epoch_time_adjustment { 0, 0 }; 108 Atomic<u32> m_update2 { 0 }; 109 110 u32 m_time_ticks_per_second { 0 }; // may be different from interrupts/second (e.g. hpet) 111 bool m_can_query_precise_time { false }; 112 bool m_updating_time { false }; // may only be accessed from the BSP! 113 114 LockRefPtr<HardwareTimerBase> m_system_timer; 115 LockRefPtr<HardwareTimerBase> m_time_keeper_timer; 116 117 Atomic<u32> m_profile_enable_count { 0 }; 118 LockRefPtr<HardwareTimerBase> m_profile_timer; 119 120 NonnullOwnPtr<Memory::Region> m_time_page_region; 121}; 122 123}