summaryrefslogtreecommitdiff
path: root/Kernel/Time
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-02-26 17:17:57 -0700
committerAndreas Kling <kling@serenityos.org>2021-02-28 15:27:53 +0100
commit32d9534c67ab8b9cfcf2d9ad7e4762424db792ba (patch)
tree24cba62e57d3010b37f15256db56883b685d91a4 /Kernel/Time
parent183ebaee91a6a5b7ca2b8a91395e562070630c48 (diff)
downloadserenity-32d9534c67ab8b9cfcf2d9ad7e4762424db792ba.zip
Kernel: Fix GenericInterruptHandler problems with virtual functions
Because registering and unregistering interrupt handlers triggers calls to virtual functions, we can't do this in the constructor and destructor. Fixes #5539
Diffstat (limited to 'Kernel/Time')
-rw-r--r--Kernel/Time/APICTimer.cpp6
-rw-r--r--Kernel/Time/APICTimer.h1
-rw-r--r--Kernel/Time/HPETComparator.cpp4
-rw-r--r--Kernel/Time/HardwareTimer.h16
4 files changed, 23 insertions, 4 deletions
diff --git a/Kernel/Time/APICTimer.cpp b/Kernel/Time/APICTimer.cpp
index fb81ba0435..6b68563d5c 100644
--- a/Kernel/Time/APICTimer.cpp
+++ b/Kernel/Time/APICTimer.cpp
@@ -38,12 +38,12 @@ namespace Kernel {
UNMAP_AFTER_INIT APICTimer* APICTimer::initialize(u8 interrupt_number, HardwareTimerBase& calibration_source)
{
- auto* timer = new APICTimer(interrupt_number, nullptr);
+ auto timer = adopt(*new APICTimer(interrupt_number, nullptr));
+ timer->register_interrupt_handler();
if (!timer->calibrate(calibration_source)) {
- delete timer;
return nullptr;
}
- return timer;
+ return &timer.leak_ref();
}
UNMAP_AFTER_INIT APICTimer::APICTimer(u8 interrupt_number, Function<void(const RegisterState&)> callback)
diff --git a/Kernel/Time/APICTimer.h b/Kernel/Time/APICTimer.h
index 7e9b24e630..8ed4f147e3 100644
--- a/Kernel/Time/APICTimer.h
+++ b/Kernel/Time/APICTimer.h
@@ -51,6 +51,7 @@ public:
virtual bool is_capable_of_frequency(size_t frequency) const override;
virtual size_t calculate_nearest_possible_frequency(size_t frequency) const override;
+ void will_be_destroyed() { HardwareTimer<GenericInterruptHandler>::will_be_destroyed(); }
void enable_local_timer();
void disable_local_timer();
diff --git a/Kernel/Time/HPETComparator.cpp b/Kernel/Time/HPETComparator.cpp
index 78d438bb19..f47f4dca0d 100644
--- a/Kernel/Time/HPETComparator.cpp
+++ b/Kernel/Time/HPETComparator.cpp
@@ -33,7 +33,9 @@ namespace Kernel {
UNMAP_AFTER_INIT NonnullRefPtr<HPETComparator> HPETComparator::create(u8 number, u8 irq, bool periodic_capable)
{
- return adopt(*new HPETComparator(number, irq, periodic_capable));
+ auto timer = adopt(*new HPETComparator(number, irq, periodic_capable));
+ timer->register_interrupt_handler();
+ return timer;
}
UNMAP_AFTER_INIT HPETComparator::HPETComparator(u8 number, u8 irq, bool periodic_capable)
diff --git a/Kernel/Time/HardwareTimer.h b/Kernel/Time/HardwareTimer.h
index c5998e1cb9..5790cf97ab 100644
--- a/Kernel/Time/HardwareTimer.h
+++ b/Kernel/Time/HardwareTimer.h
@@ -49,6 +49,12 @@ class HardwareTimerBase
public:
virtual ~HardwareTimerBase() { }
+ // We need to create a virtual will_be_destroyed here because we derive
+ // from RefCounted<HardwareTimerBase> here, which means that RefCounted<>
+ // will only call will_be_destroyed if we define it here. The derived
+ // classes then should forward this to e.g. GenericInterruptHandler.
+ virtual void will_be_destroyed() = 0;
+
virtual const char* model() const = 0;
virtual HardwareTimerType timer_type() const = 0;
virtual Function<void(const RegisterState&)> set_callback(Function<void(const RegisterState&)>) = 0;
@@ -73,6 +79,11 @@ class HardwareTimer<IRQHandler>
: public HardwareTimerBase
, public IRQHandler {
public:
+ virtual void will_be_destroyed() override
+ {
+ IRQHandler::will_be_destroyed();
+ }
+
virtual const char* purpose() const override
{
if (TimeManagement::the().is_system_timer(*this))
@@ -115,6 +126,11 @@ class HardwareTimer<GenericInterruptHandler>
: public HardwareTimerBase
, public GenericInterruptHandler {
public:
+ virtual void will_be_destroyed() override
+ {
+ GenericInterruptHandler::will_be_destroyed();
+ }
+
virtual const char* purpose() const override
{
return model();