1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 03:37:43 +00:00

Kernel: Don't use the profile timer if we don't have a timer to assign

This commit is contained in:
Liav A 2021-05-14 11:33:34 +03:00 committed by Andreas Kling
parent a5801e9919
commit 8a4cc735b9
3 changed files with 43 additions and 21 deletions

View file

@ -30,12 +30,13 @@ KResultOr<int> Process::sys$profiling_enable(pid_t pid)
g_global_perf_events = PerformanceEventBuffer::try_create_with_size(32 * MiB).leak_ptr(); g_global_perf_events = PerformanceEventBuffer::try_create_with_size(32 * MiB).leak_ptr();
ScopedSpinLock lock(g_processes_lock); ScopedSpinLock lock(g_processes_lock);
g_profiling_all_threads = true; if (!TimeManagement::the().enable_profile_timer())
return ENOTSUP;
Process::for_each([](auto& process) { Process::for_each([](auto& process) {
PerformanceManager::add_process_created_event(process); PerformanceManager::add_process_created_event(process);
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
TimeManagement::the().enable_profile_timer(); g_profiling_all_threads = true;
return 0; return 0;
} }
@ -49,8 +50,9 @@ KResultOr<int> Process::sys$profiling_enable(pid_t pid)
return EPERM; return EPERM;
if (!process->create_perf_events_buffer_if_needed()) if (!process->create_perf_events_buffer_if_needed())
return ENOMEM; return ENOMEM;
if (!TimeManagement::the().enable_profile_timer())
return ENOTSUP;
process->set_profiling(true); process->set_profiling(true);
TimeManagement::the().enable_profile_timer();
return 0; return 0;
} }
@ -62,8 +64,9 @@ KResultOr<int> Process::sys$profiling_disable(pid_t pid)
if (!is_superuser()) if (!is_superuser())
return EPERM; return EPERM;
ScopedCritical critical; ScopedCritical critical;
if (!TimeManagement::the().disable_profile_timer())
return ENOTSUP;
g_profiling_all_threads = false; g_profiling_all_threads = false;
TimeManagement::the().disable_profile_timer();
return 0; return 0;
} }
@ -75,7 +78,9 @@ KResultOr<int> Process::sys$profiling_disable(pid_t pid)
return EPERM; return EPERM;
if (!process->is_profiling()) if (!process->is_profiling())
return EINVAL; return EINVAL;
TimeManagement::the().disable_profile_timer(); // FIXME: If we enabled the profile timer and it's not supported, how do we disable it now?
if (!TimeManagement::the().disable_profile_timer())
return ENOTSUP;
process->set_profiling(false); process->set_profiling(false);
return 0; return 0;
} }

View file

@ -262,10 +262,16 @@ UNMAP_AFTER_INIT bool TimeManagement::probe_and_set_non_legacy_hardware_timers()
VERIFY(periodic_timers.size() + non_periodic_timers.size() > 0); VERIFY(periodic_timers.size() + non_periodic_timers.size() > 0);
if (periodic_timers.size() > 0) size_t taken_periodic_timers_count = 0;
m_system_timer = periodic_timers[0]; size_t taken_non_periodic_timers_count = 0;
else
m_system_timer = non_periodic_timers[0]; if (periodic_timers.size() > taken_periodic_timers_count) {
m_system_timer = periodic_timers[taken_periodic_timers_count];
taken_periodic_timers_count += 1;
} else if (non_periodic_timers.size() > taken_non_periodic_timers_count) {
m_system_timer = non_periodic_timers[taken_non_periodic_timers_count];
taken_non_periodic_timers_count += 1;
}
m_system_timer->set_callback([this](const RegisterState& regs) { m_system_timer->set_callback([this](const RegisterState& regs) {
// Update the time. We don't really care too much about the // Update the time. We don't really care too much about the
@ -291,13 +297,18 @@ UNMAP_AFTER_INIT bool TimeManagement::probe_and_set_non_legacy_hardware_timers()
// can query the timer. // can query the timer.
m_time_keeper_timer = m_system_timer; m_time_keeper_timer = m_system_timer;
if (periodic_timers.size() > 1) if (periodic_timers.size() > taken_periodic_timers_count) {
m_profile_timer = periodic_timers[1]; m_profile_timer = periodic_timers[taken_periodic_timers_count];
else taken_periodic_timers_count += 1;
m_profile_timer = non_periodic_timers[1]; } else if (non_periodic_timers.size() > taken_non_periodic_timers_count) {
m_profile_timer = non_periodic_timers[taken_non_periodic_timers_count];
taken_non_periodic_timers_count += 1;
}
m_profile_timer->set_callback(PerformanceManager::timer_tick); if (m_profile_timer) {
m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(1)); m_profile_timer->set_callback(PerformanceManager::timer_tick);
m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(1));
}
return true; return true;
} }
@ -389,16 +400,22 @@ void TimeManagement::system_timer_tick(const RegisterState& regs)
Scheduler::timer_tick(regs); Scheduler::timer_tick(regs);
} }
void TimeManagement::enable_profile_timer() bool TimeManagement::enable_profile_timer()
{ {
if (m_profile_enable_count.fetch_add(1) == 0) if (m_profile_timer && m_profile_enable_count.fetch_add(1) == 0) {
m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE)); m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(OPTIMAL_PROFILE_TICKS_PER_SECOND_RATE));
return true;
}
return false;
} }
void TimeManagement::disable_profile_timer() bool TimeManagement::disable_profile_timer()
{ {
if (m_profile_enable_count.fetch_sub(1) == 1) if (m_profile_timer && m_profile_enable_count.fetch_sub(1) == 1) {
m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(1)); m_profile_timer->try_to_set_frequency(m_profile_timer->calculate_nearest_possible_frequency(1));
return true;
}
return false;
} }
} }

View file

@ -56,8 +56,8 @@ public:
static bool is_hpet_periodic_mode_allowed(); static bool is_hpet_periodic_mode_allowed();
void enable_profile_timer(); bool enable_profile_timer();
void disable_profile_timer(); bool disable_profile_timer();
u64 uptime_ms() const; u64 uptime_ms() const;
static Time now(); static Time now();