diff --git a/Kernel/Graphics/VMWare/Console.cpp b/Kernel/Graphics/VMWare/Console.cpp index ee5e451024..b55bab0722 100644 --- a/Kernel/Graphics/VMWare/Console.cpp +++ b/Kernel/Graphics/VMWare/Console.cpp @@ -39,7 +39,7 @@ void VMWareFramebufferConsole::flush(size_t, size_t, size_t, size_t) void VMWareFramebufferConsole::enqueue_refresh_timer() { - NonnullLockRefPtr refresh_timer = adopt_lock_ref(*new (nothrow) Timer()); + auto refresh_timer = adopt_nonnull_ref_or_enomem(new (nothrow) Timer()).release_value_but_fixme_should_propagate_errors(); refresh_timer->setup(CLOCK_MONOTONIC, refresh_interval, [this]() { if (m_enabled.load() && m_dirty) { MUST(g_io_work->try_queue([this]() { diff --git a/Kernel/Graphics/VirtIOGPU/Console.cpp b/Kernel/Graphics/VirtIOGPU/Console.cpp index 5b2d5b8c9d..2979af1421 100644 --- a/Kernel/Graphics/VirtIOGPU/Console.cpp +++ b/Kernel/Graphics/VirtIOGPU/Console.cpp @@ -67,7 +67,7 @@ void Console::flush(size_t, size_t, size_t, size_t) void Console::enqueue_refresh_timer() { - NonnullLockRefPtr refresh_timer = adopt_lock_ref(*new Timer()); + auto refresh_timer = adopt_nonnull_ref_or_enomem(new (nothrow) Timer()).release_value_but_fixme_should_propagate_errors(); refresh_timer->setup(CLOCK_MONOTONIC, refresh_interval, [this]() { if (m_enabled.load() && m_dirty) { MUST(g_io_work->try_queue([this]() { diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 77b0d9694e..aca0928f09 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -364,7 +364,6 @@ Process::~Process() unprotect_data(); VERIFY(thread_count() == 0); // all threads should have been finalized - VERIFY(!m_alarm_timer); PerformanceManager::add_process_exit_event(*this); } @@ -754,8 +753,10 @@ void Process::finalize() m_threads_for_coredump.clear(); - if (m_alarm_timer) - TimerQueue::the().cancel_timer(m_alarm_timer.release_nonnull()); + m_alarm_timer.with([&](auto& timer) { + if (timer) + TimerQueue::the().cancel_timer(timer.release_nonnull()); + }); m_fds.with_exclusive([](auto& fds) { fds.clear(); }); m_tty = nullptr; m_executable.with([](auto& executable) { executable = nullptr; }); diff --git a/Kernel/Process.h b/Kernel/Process.h index 9a8448a48d..dbcc335d61 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -875,7 +875,7 @@ private: Mutex m_big_lock { "Process"sv, Mutex::MutexBehavior::BigLock }; Mutex m_ptrace_lock { "ptrace"sv }; - LockRefPtr m_alarm_timer; + SpinlockProtected, LockRank::None> m_alarm_timer; SpinlockProtected m_unveil_data; SpinlockProtected m_exec_unveil_data; diff --git a/Kernel/Syscalls/alarm.cpp b/Kernel/Syscalls/alarm.cpp index 2ff757cd4d..c73458d482 100644 --- a/Kernel/Syscalls/alarm.cpp +++ b/Kernel/Syscalls/alarm.cpp @@ -15,31 +15,33 @@ ErrorOr Process::sys$alarm(unsigned seconds) VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); TRY(require_promise(Pledge::stdio)); unsigned previous_alarm_remaining = 0; - if (m_alarm_timer) { - bool was_in_use = false; - if (TimerQueue::the().cancel_timer(*m_alarm_timer, &was_in_use)) { - // The timer hasn't fired. Round up the remaining time (if any) - Time remaining = m_alarm_timer->remaining() + Time::from_nanoseconds(999'999'999); - previous_alarm_remaining = remaining.to_truncated_seconds(); + return m_alarm_timer.with([&](auto& timer) -> ErrorOr { + if (timer) { + bool was_in_use = false; + if (TimerQueue::the().cancel_timer(*timer, &was_in_use)) { + // The timer hasn't fired. Round up the remaining time (if any) + Time remaining = timer->remaining() + Time::from_nanoseconds(999'999'999); + previous_alarm_remaining = remaining.to_truncated_seconds(); + } + // We had an existing alarm, must return a non-zero value here! + if (was_in_use && previous_alarm_remaining == 0) + previous_alarm_remaining = 1; } - // We had an existing alarm, must return a non-zero value here! - if (was_in_use && previous_alarm_remaining == 0) - previous_alarm_remaining = 1; - } - if (seconds > 0) { - auto deadline = TimeManagement::the().current_time(CLOCK_REALTIME_COARSE); - deadline = deadline + Time::from_seconds(seconds); - if (!m_alarm_timer) { - m_alarm_timer = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) Timer)); + if (seconds > 0) { + auto deadline = TimeManagement::the().current_time(CLOCK_REALTIME_COARSE); + deadline = deadline + Time::from_seconds(seconds); + if (!timer) { + timer = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Timer)); + } + auto timer_was_added = TimerQueue::the().add_timer_without_id(*timer, CLOCK_REALTIME_COARSE, deadline, [this]() { + MUST(send_signal(SIGALRM, nullptr)); + }); + if (!timer_was_added) + return ENOMEM; } - auto timer_was_added = TimerQueue::the().add_timer_without_id(*m_alarm_timer, CLOCK_REALTIME_COARSE, deadline, [this]() { - MUST(send_signal(SIGALRM, nullptr)); - }); - if (!timer_was_added) - return ENOMEM; - } - return previous_alarm_remaining; + return previous_alarm_remaining; + }); } } diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 30365031b5..38fde59613 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -44,13 +44,13 @@ ErrorOr> Thread::create(NonnullRefPtr process) auto kernel_stack_region = TRY(MM.allocate_kernel_region(default_kernel_stack_size, {}, Memory::Region::Access::ReadWrite, AllocationStrategy::AllocateNow)); kernel_stack_region->set_stack(true); - auto block_timer = TRY(try_make_lock_ref_counted()); + auto block_timer = TRY(try_make_ref_counted()); auto name = TRY(process->name().with([](auto& name) { return name->try_clone(); })); return adopt_nonnull_ref_or_enomem(new (nothrow) Thread(move(process), move(kernel_stack_region), move(block_timer), move(name))); } -Thread::Thread(NonnullRefPtr process, NonnullOwnPtr kernel_stack_region, NonnullLockRefPtr block_timer, NonnullOwnPtr name) +Thread::Thread(NonnullRefPtr process, NonnullOwnPtr kernel_stack_region, NonnullRefPtr block_timer, NonnullOwnPtr name) : m_process(move(process)) , m_kernel_stack_region(move(kernel_stack_region)) , m_name(move(name)) diff --git a/Kernel/Thread.h b/Kernel/Thread.h index ae48eba786..8e8b9d7d32 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1083,7 +1083,7 @@ public: #endif private: - Thread(NonnullRefPtr, NonnullOwnPtr, NonnullLockRefPtr, NonnullOwnPtr); + Thread(NonnullRefPtr, NonnullOwnPtr, NonnullRefPtr, NonnullOwnPtr); BlockResult block_impl(BlockTimeout const&, Blocker&); @@ -1235,7 +1235,7 @@ private: Atomic m_have_any_unmasked_pending_signals { false }; Atomic m_nested_profiler_calls { 0 }; - NonnullLockRefPtr m_block_timer; + NonnullRefPtr const m_block_timer; bool m_is_profiling_suppressed { false }; diff --git a/Kernel/TimerQueue.cpp b/Kernel/TimerQueue.cpp index 157af5c6d0..bcb7001e74 100644 --- a/Kernel/TimerQueue.cpp +++ b/Kernel/TimerQueue.cpp @@ -55,14 +55,14 @@ UNMAP_AFTER_INIT TimerQueue::TimerQueue() m_ticks_per_second = TimeManagement::the().ticks_per_second(); } -bool TimerQueue::add_timer_without_id(NonnullLockRefPtr timer, clockid_t clock_id, Time const& deadline, Function&& callback) +bool TimerQueue::add_timer_without_id(NonnullRefPtr timer, clockid_t clock_id, Time const& deadline, Function&& callback) { if (deadline <= TimeManagement::the().current_time(clock_id)) return false; // Because timer handlers can execute on any processor and there is // a race between executing a timer handler and cancel_timer() this - // *must* be a LockRefPtr. Otherwise, calling cancel_timer() could + // *must* be a RefPtr. Otherwise, calling cancel_timer() could // inadvertently cancel another timer that has been created between // returning from the timer handler and a call to cancel_timer(). timer->setup(clock_id, deadline, move(callback)); @@ -73,7 +73,7 @@ bool TimerQueue::add_timer_without_id(NonnullLockRefPtr timer, clockid_t return true; } -TimerId TimerQueue::add_timer(NonnullLockRefPtr&& timer) +TimerId TimerQueue::add_timer(NonnullRefPtr&& timer) { SpinlockLocker lock(g_timerqueue_lock); @@ -84,7 +84,7 @@ TimerId TimerQueue::add_timer(NonnullLockRefPtr&& timer) return id; } -void TimerQueue::add_timer_locked(NonnullLockRefPtr timer) +void TimerQueue::add_timer_locked(NonnullRefPtr timer) { Time timer_expiration = timer->m_expires; diff --git a/Kernel/TimerQueue.h b/Kernel/TimerQueue.h index d309315979..049f95b1da 100644 --- a/Kernel/TimerQueue.h +++ b/Kernel/TimerQueue.h @@ -87,8 +87,8 @@ public: TimerQueue(); static TimerQueue& the(); - TimerId add_timer(NonnullLockRefPtr&&); - bool add_timer_without_id(NonnullLockRefPtr, clockid_t, Time const&, Function&&); + TimerId add_timer(NonnullRefPtr&&); + bool add_timer_without_id(NonnullRefPtr, clockid_t, Time const&, Function&&); bool cancel_timer(Timer& timer, bool* was_in_use = nullptr); void fire(); @@ -99,7 +99,7 @@ private: }; void remove_timer_locked(Queue&, Timer&); void update_next_timer_due(Queue&); - void add_timer_locked(NonnullLockRefPtr); + void add_timer_locked(NonnullRefPtr); Queue& queue_for_timer(Timer& timer) {