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 unsigned _stall_detector_reports_per_minute;
59 std::atomic<uint64_t> _stall_detector_missed_ticks = { 0 };
60 unsigned _reported = 0;
61 unsigned _total_reported = 0;
62 unsigned _max_reports_per_minute;
65 unsigned _report_at{};
66 sched_clock::time_point _minute_mark{};
67 sched_clock::time_point _rearm_timer_at{};
68 sched_clock::time_point _run_started_at{};
69 sched_clock::duration _threshold;
70 sched_clock::duration _slack;
71 cpu_stall_detector_config _config;
74 virtual bool is_spurious_signal() {
77 virtual void maybe_report_kernel_trace() {}
80 virtual void arm_timer() = 0;
81 void report_suppressions(sched_clock::time_point
now);
82 void reset_suppression_state(sched_clock::time_point
now);
84 using clock_type = thread_cputime_clock;
86 explicit cpu_stall_detector(cpu_stall_detector_config cfg = {});
87 virtual ~cpu_stall_detector() =
default;
88 static int signal_number() {
return SIGRTMIN + 1; }
89 void start_task_run(sched_clock::time_point
now);
90 void end_task_run(sched_clock::time_point
now);
91 void generate_trace();
92 void update_config(cpu_stall_detector_config cfg);
93 cpu_stall_detector_config get_config()
const;
95 virtual void start_sleep() = 0;
99class cpu_stall_detector_posix_timer :
public cpu_stall_detector {
102 explicit cpu_stall_detector_posix_timer(cpu_stall_detector_config cfg = {});
103 virtual ~cpu_stall_detector_posix_timer()
override;
105 virtual void arm_timer()
override;
106 virtual void start_sleep()
override;
109class cpu_stall_detector_linux_perf_event :
public cpu_stall_detector {
111 bool _enabled =
false;
112 uint64_t _current_period = 0;
113 struct ::perf_event_mmap_page* _mmap;
115 size_t _data_area_mask;
119 sched_clock::time_point _next_signal_time{};
121 class data_area_reader {
122 cpu_stall_detector_linux_perf_event& _p;
123 const char* _data_area;
124 size_t _data_area_mask;
128 explicit data_area_reader(cpu_stall_detector_linux_perf_event& p)
130 , _data_area(p._data_area)
131 , _data_area_mask(p._data_area_mask) {
132 _head = _p._mmap->data_head;
133 _tail = _p._mmap->data_tail;
134 std::atomic_thread_fence(std::memory_order_acquire);
136 ~data_area_reader() {
137 std::atomic_thread_fence(std::memory_order_release);
138 _p._mmap->data_tail = _tail;
140 uint64_t read_u64() {
143 std::copy_n(_data_area + (_tail & _data_area_mask), 8,
reinterpret_cast<char*
>(&ret));
147 template <
typename S>
149 static_assert(
sizeof(S) % 8 == 0);
151 char* p =
reinterpret_cast<char*
>(&ret);
152 for (
size_t i = 0; i !=
sizeof(S); i += 8) {
153 uint64_t w = read_u64();
154 std::copy_n(
reinterpret_cast<const char*
>(&w), 8, p + i);
158 void skip(uint64_t bytes_to_skip) {
159 _tail += bytes_to_skip;
166 bool have_data()
const {
167 return _head != _tail;
171 static std::unique_ptr<cpu_stall_detector_linux_perf_event> try_make(cpu_stall_detector_config cfg = {});
172 explicit cpu_stall_detector_linux_perf_event(file_desc fd, cpu_stall_detector_config cfg = {});
173 ~cpu_stall_detector_linux_perf_event();
174 virtual void arm_timer()
override;
175 virtual void start_sleep()
override;
176 virtual bool is_spurious_signal()
override;
177 virtual void maybe_report_kernel_trace()
override;
180std::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