1use std::ffi::c_void;
2
3use crate::preset::{THREAD_RESTORE, THREAD_THROTTLE, THREAD_UNTHROTTLE};
4use windows::Win32::{
5 Foundation::{CloseHandle, HANDLE},
6 System::Threading::{
7 GetThreadInformation, OpenThread, SetThreadInformation, SetThreadPriority,
8 ThreadPowerThrottling, THREAD_INFORMATION_CLASS, THREAD_POWER_THROTTLING_CURRENT_VERSION,
9 THREAD_POWER_THROTTLING_EXECUTION_SPEED, THREAD_POWER_THROTTLING_STATE, THREAD_PRIORITY,
10 THREAD_PRIORITY_IDLE, THREAD_PRIORITY_NORMAL, THREAD_SET_INFORMATION,
11 },
12};
13
14unsafe fn toggle_efficiency_mode_impl(
15 hthread: HANDLE,
16 threadinformation: *const c_void,
17 threadinformationclass: THREAD_INFORMATION_CLASS,
18 threadinformationsize: u32,
19 npriority: THREAD_PRIORITY,
20) -> Result<(), windows_result::Error> {
21 unsafe {
22 SetThreadInformation(
23 hthread,
24 threadinformationclass,
25 threadinformation,
26 threadinformationsize,
27 )?;
28 SetThreadPriority(hthread, npriority)?;
29 }
30
31 Ok(())
32}
33
34pub fn toggle_efficiency_mode(
42 thread_id: u32,
43 enable: Option<bool>,
44) -> Result<(), windows_result::Error> {
45 let hthread = unsafe { OpenThread(THREAD_SET_INFORMATION, false, thread_id)? };
46 let result = unsafe { toggle_efficiency_mode_handle(hthread, enable) };
47 let _ = unsafe { CloseHandle(hthread) };
48
49 result
50}
51
52pub unsafe fn toggle_efficiency_mode_handle(
62 hthread: HANDLE,
63 enable: Option<bool>,
64) -> Result<(), windows_result::Error> {
65 let new_state = match enable {
66 Some(true) => THREAD_THROTTLE,
67 Some(false) => THREAD_UNTHROTTLE,
68 None => THREAD_RESTORE,
69 };
70
71 let threadinformationclass = ThreadPowerThrottling;
72 let threadinformation = &new_state as *const _ as *const c_void;
73 let threadinformationsize = size_of::<THREAD_POWER_THROTTLING_STATE>() as u32;
74
75 let npriority = if let Some(true) = enable {
76 THREAD_PRIORITY_IDLE
77 } else {
78 THREAD_PRIORITY_NORMAL
79 };
80
81 unsafe {
82 toggle_efficiency_mode_impl(
83 hthread,
84 threadinformation,
85 threadinformationclass,
86 threadinformationsize,
87 npriority,
88 )
89 }
90}
91
92pub unsafe fn ecoqos_enabled(hthread: HANDLE) -> Result<bool, windows_result::Error> {
98 let mut thread_info = THREAD_POWER_THROTTLING_STATE {
99 Version: THREAD_POWER_THROTTLING_CURRENT_VERSION,
100 ..Default::default()
101 };
102
103 unsafe {
104 GetThreadInformation(
105 hthread,
106 ThreadPowerThrottling,
107 &mut thread_info as *mut _ as *mut _,
108 size_of::<THREAD_POWER_THROTTLING_STATE>() as u32,
109 )?;
110 }
111
112 Ok(
113 thread_info.StateMask & THREAD_POWER_THROTTLING_EXECUTION_SPEED
114 == THREAD_POWER_THROTTLING_EXECUTION_SPEED,
115 )
116}