darkfi/system/
thread_priority.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2026 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19/// Levels of thread priority
20pub enum ThreadPriority {
21    Min,
22    Low,
23    Normal,
24    High,
25    Max,
26}
27
28/// Set current thread priority to given `priority`.
29/// This usually requires root privileges.
30pub fn set_thread_priority(priority: ThreadPriority) {
31    #[cfg(windows)]
32    {
33        type HANDLE = *mut std::ffi::c_void;
34
35        const THREAD_PRIORITY_IDLE: i32 = -15;
36        const THREAD_PRIORITY_BELOW_NORMAL: i32 = -1;
37        const THREAD_PRIORITY_NORMAL: i32 = 0;
38        const THREAD_PRIORITY_ABOVE_NORMAL: i32 = 1;
39        const THREAD_PRIORITY_TIME_CRITICAL: i32 = 15;
40
41        extern "system" {
42            fn GetCurrentThread() -> HANDLE;
43            fn SetThreadPriority(hThread: HANDLE, nPriority: i32) -> i32;
44        }
45
46        let priority_value = match priority {
47            ThreadPriority::Min => THREAD_PRIORITY_IDLE,
48            ThreadPriority::Low => THREAD_PRIORITY_BELOW_NORMAL,
49            ThreadPriority::Normal => THREAD_PRIORITY_NORMAL,
50            ThreadPriority::High => THREAD_PRIORITY_ABOVE_NORMAL,
51            ThreadPriority::Max => THREAD_PRIORITY_TIME_CRITICAL,
52        };
53
54        unsafe {
55            SetThreadPriority(GetCurrentThread(), priority_value);
56        }
57    }
58
59    #[cfg(any(target_os = "linux", target_os = "android"))]
60    {
61        // For android see:
62        // https://github.com/android/ndk/issues/1255#issuecomment-1426545936
63
64        extern "C" {
65            fn setpriority(which: i32, who: u32, prio: i32) -> i32;
66        }
67
68        const PRIO_PROCESS: i32 = 0;
69
70        let nice_value = match priority {
71            ThreadPriority::Min => 19,
72            ThreadPriority::Low => 10,
73            ThreadPriority::Normal => 0,
74            ThreadPriority::High => -10,
75            ThreadPriority::Max => -20,
76        };
77
78        unsafe {
79            setpriority(PRIO_PROCESS, std::process::id(), nice_value);
80        }
81    }
82
83    #[cfg(any(target_os = "macos", target_os = "ios"))]
84    {
85        type mach_port_t = u32;
86        type thread_t = mach_port_t;
87        type thread_policy_flavor_t = i32;
88        type thread_policy_t = *mut i32;
89        type mach_msg_type_number_t = u32;
90
91        const THREAD_PRECEDENCE_POLICY: thread_policy_flavor_t = 3;
92
93        #[repr(C)]
94        struct thread_precedence_policy_data {
95            importance: i32,
96        }
97
98        extern "C" {
99            fn mach_thread_self() -> thread_t;
100            fn thread_policy_set(
101                thread: thread_t,
102                flavor: thread_policy_flavor_t,
103                policy_info: thread_policy_t,
104                count: mach_msg_type_number_t,
105            ) -> i32;
106        }
107
108        let importance = match priority {
109            ThreadPriority::Min => -30,
110            ThreadPriority::Low => -15,
111            ThreadPriority::Normal => 0,
112            ThreadPriority::High => 15,
113            ThreadPriority::Max => 30,
114        };
115
116        unsafe {
117            let thread = mach_thread_self();
118            let mut policy = thread_precedence_policy_data { importance };
119            let count =
120                std::mem::size_of::<thread_precedence_policy_data>() as mach_msg_type_number_t / 4;
121
122            thread_policy_set(
123                thread,
124                THREAD_PRECEDENCE_POLICY,
125                &mut policy as *mut _ as thread_policy_t,
126                count,
127            );
128        }
129    }
130}