1pub use thread_priority::{self, *};
4
5#[macro_export]
11macro_rules! once {
12 ($e:expr) => {{
13 static ONCE: std::sync::Once = std::sync::Once::new();
14 ONCE.call_once($e);
15 }};
16}
17
18pub fn increase_thread_priority() {
24 let thread_name = std::thread::current().name().unwrap_or("unnamed").to_string();
25 if let Err(err) = ThreadPriority::Max.set_for_current() {
26 tracing::debug!(%thread_name, ?err, "failed to set max thread priority, trying moderate bump; grant CAP_SYS_NICE to the process to enable this");
27 let fallback = ThreadPriority::Crossplatform(
29 ThreadPriorityValue::try_from(62u8).expect("62 is within the valid 0..100 range"),
30 );
31 if let Err(err) = fallback.set_for_current() {
32 tracing::debug!(%thread_name, ?err, "failed to set moderate thread priority");
33 }
34 }
35}
36
37#[allow(clippy::missing_const_for_fn)]
49pub fn deprioritize_background_threads() {
50 #[cfg(target_os = "linux")]
51 _deprioritize_background_threads();
52}
53
54#[cfg(target_os = "linux")]
56const DEPRIORITIZE_THREAD_PREFIXES: &[&str] =
57 &["OpenTelemetry.T", "tracing-appende", "reqwest-interna"];
58
59#[cfg(target_os = "linux")]
60fn _deprioritize_background_threads() {
61 let pid = std::process::id();
62 let task_dir = format!("/proc/{pid}/task");
63
64 let entries = match std::fs::read_dir(&task_dir) {
65 Ok(entries) => entries,
66 Err(err) => {
67 tracing::debug!(%err, "failed to read /proc task directory");
68 return;
69 }
70 };
71
72 for entry in entries.filter_map(Result::ok) {
73 let tid_str = entry.file_name();
74 let Some(tid_str) = tid_str.to_str() else { continue };
75 let Ok(tid) = tid_str.parse::<i32>() else { continue };
76
77 let comm_path = format!("{task_dir}/{tid_str}/comm");
78 let comm = match std::fs::read_to_string(&comm_path) {
79 Ok(c) => c,
80 Err(_) => continue,
81 };
82 let comm = comm.trim();
83
84 if !DEPRIORITIZE_THREAD_PREFIXES.iter().any(|prefix| comm.starts_with(prefix)) {
85 continue;
86 }
87
88 unsafe {
92 let param = libc::sched_param { sched_priority: 0 };
93 if libc::sched_setscheduler(tid, libc::SCHED_IDLE, std::ptr::from_ref(¶m)) != 0 {
94 tracing::debug!(
95 tid,
96 comm,
97 err = std::io::Error::last_os_error().to_string(),
98 "failed to set SCHED_IDLE"
99 );
100 }
101 }
102
103 tracing::debug!(tid, comm, "deprioritized background thread (SCHED_IDLE)");
104 }
105}