32#include <linux/perf_event.h>
37#include <seastar/util/modules.hh>
42class thread_cputime_clock;
46struct cpu_stall_detector_config {
47 std::chrono::duration<double> threshold = std::chrono::seconds(2);
48 unsigned stall_detector_reports_per_minute = 1;
51 std::function<void ()> report;
55class cpu_stall_detector {
57 std::atomic<uint64_t> _last_tasks_processed_seen{};
58 std::atomic<uint64_t> _stall_detector_missed_ticks = { 0 };
59 unsigned _reported = 0;
60 unsigned _total_reported = 0;
61 unsigned _max_reports_per_minute;
64 unsigned _report_at{};
65 sched_clock::time_point _minute_mark{};
66 sched_clock::time_point _rearm_timer_at{};
67 sched_clock::time_point _run_started_at{};
68 sched_clock::duration _threshold;
69 sched_clock::duration _slack;
70 cpu_stall_detector_config _config;
73 virtual bool is_spurious_signal() {
76 virtual void maybe_report_kernel_trace() {}
79 virtual void arm_timer() = 0;
80 void report_suppressions(sched_clock::time_point
now);
81 void reset_suppression_state(sched_clock::time_point
now);
83 using clock_type = thread_cputime_clock;
85 explicit cpu_stall_detector(cpu_stall_detector_config cfg = {});
86 virtual ~cpu_stall_detector() =
default;
87 static int signal_number() {
return SIGRTMIN + 1; }
88 void start_task_run(sched_clock::time_point
now);
89 void end_task_run(sched_clock::time_point
now);
90 void generate_trace();
91 void update_config(cpu_stall_detector_config cfg);
92 cpu_stall_detector_config get_config()
const;
94 virtual void start_sleep() = 0;
98class cpu_stall_detector_posix_timer :
public cpu_stall_detector {
101 explicit cpu_stall_detector_posix_timer(cpu_stall_detector_config cfg = {});
102 virtual ~cpu_stall_detector_posix_timer()
override;
104 virtual void arm_timer()
override;
105 virtual void start_sleep()
override;
108class cpu_stall_detector_linux_perf_event :
public cpu_stall_detector {
110 bool _enabled =
false;
111 uint64_t _current_period = 0;
112 struct ::perf_event_mmap_page* _mmap;
114 size_t _data_area_mask;
118 sched_clock::time_point _next_signal_time{};
120 class data_area_reader {
121 cpu_stall_detector_linux_perf_event& _p;
122 const char* _data_area;
123 size_t _data_area_mask;
127 explicit data_area_reader(cpu_stall_detector_linux_perf_event& p)
129 , _data_area(p._data_area)
130 , _data_area_mask(p._data_area_mask) {
131 _head = _p._mmap->data_head;
132 _tail = _p._mmap->data_tail;
133 std::atomic_thread_fence(std::memory_order_acquire);
135 ~data_area_reader() {
136 std::atomic_thread_fence(std::memory_order_release);
137 _p._mmap->data_tail = _tail;
139 uint64_t read_u64() {
142 std::copy_n(_data_area + (_tail & _data_area_mask), 8,
reinterpret_cast<char*
>(&ret));
146 template <
typename S>
148 static_assert(
sizeof(S) % 8 == 0);
150 char* p =
reinterpret_cast<char*
>(&ret);
151 for (
size_t i = 0; i !=
sizeof(S); i += 8) {
152 uint64_t w = read_u64();
153 std::copy_n(
reinterpret_cast<const char*
>(&w), 8, p + i);
157 void skip(uint64_t bytes_to_skip) {
158 _tail += bytes_to_skip;
165 bool have_data()
const {
166 return _head != _tail;
170 static std::unique_ptr<cpu_stall_detector_linux_perf_event> try_make(cpu_stall_detector_config cfg = {});
171 explicit cpu_stall_detector_linux_perf_event(file_desc fd, cpu_stall_detector_config cfg = {});
172 ~cpu_stall_detector_linux_perf_event();
173 virtual void arm_timer()
override;
174 virtual void start_sleep()
override;
175 virtual bool is_spurious_signal()
override;
176 virtual void maybe_report_kernel_trace()
override;
179std::unique_ptr<cpu_stall_detector> make_cpu_stall_detector(cpu_stall_detector_config cfg = {});
holds the metric definition.
Definition: metrics_registration.hh:94
future now()
Returns a ready future.
Definition: later.hh:35
holds the metric_groups definition needed by class that reports metrics
Seastar API namespace.
Definition: abort_on_ebadf.hh:26