Skip to content

Commit e8d1466

Browse files
committed
top: cpu time for windows
1 parent 195ee90 commit e8d1466

File tree

3 files changed

+57
-44
lines changed

3 files changed

+57
-44
lines changed

src/uu/top/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bytesize = { workspace = true }
2626
libsystemd-sys = "0.9.3"
2727

2828
[target.'cfg(target_os="windows")'.dependencies]
29-
windows = { version = "0.59.0", features = ["Win32_System_RemoteDesktop"] }
29+
windows = { version = "0.59.0", features = ["Win32_System_RemoteDesktop", "Wdk_System_SystemInformation"] }
3030

3131
[lib]
3232
path = "src/top.rs"

src/uu/top/src/header.rs

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,6 @@ use crate::picker::{sysinfo, systemstat};
77
use bytesize::ByteSize;
88
use clap::ArgMatches;
99
use systemstat::Platform;
10-
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
11-
use {
12-
std::sync::{Mutex, OnceLock},
13-
systemstat::{CPULoad, DelayedMeasurement},
14-
};
15-
16-
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
17-
static LOAD_AVERAGE: OnceLock<Mutex<DelayedMeasurement<CPULoad>>> = OnceLock::new();
18-
19-
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
20-
pub(crate) fn cpu_load() -> CPULoad {
21-
match LOAD_AVERAGE.get() {
22-
None => {
23-
LOAD_AVERAGE.get_or_init(|| {
24-
Mutex::new(systemstat().read().unwrap().cpu_load_aggregate().unwrap())
25-
});
26-
systemstat()
27-
.read()
28-
.unwrap()
29-
.cpu_load_aggregate()
30-
.unwrap()
31-
.done()
32-
.unwrap()
33-
}
34-
Some(v) => {
35-
let mut v = v.lock().unwrap();
36-
let load = v.done().unwrap();
37-
*v = systemstat().read().unwrap().cpu_load_aggregate().unwrap();
38-
load
39-
}
40-
}
41-
}
4210

4311
pub(crate) fn header(arg: &ArgMatches) -> String {
4412
format!(
@@ -298,16 +266,64 @@ fn cpu() -> String {
298266
)
299267
}
300268

301-
//TODO: Implement io wait, hardware interrupt, software interrupt and steal time
302-
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
269+
#[cfg(target_os = "windows")]
303270
fn cpu() -> String {
304-
let cpu = cpu_load();
271+
use libc::malloc;
272+
use windows::Wdk::System::SystemInformation::NtQuerySystemInformation;
273+
274+
#[repr(C)]
275+
#[derive(Debug)]
276+
struct SystemProcessorPerformanceInformation {
277+
idle_time: i64, // LARGE_INTEGER
278+
kernel_time: i64, // LARGE_INTEGER
279+
user_time: i64, // LARGE_INTEGER
280+
dpc_time: i64, // LARGE_INTEGER
281+
interrupt_time: i64, // LARGE_INTEGER
282+
interrupt_count: u32, // ULONG
283+
}
284+
285+
let n_cpu = sysinfo().read().unwrap().cpus().len();
286+
let mut cpu_load = SystemProcessorPerformanceInformation {
287+
idle_time: 0,
288+
kernel_time: 0,
289+
user_time: 0,
290+
dpc_time: 0,
291+
interrupt_time: 0,
292+
interrupt_count: 0,
293+
};
294+
unsafe {
295+
let len = n_cpu * size_of::<SystemProcessorPerformanceInformation>();
296+
let data = malloc(len);
297+
let _ = NtQuerySystemInformation(
298+
windows::Wdk::System::SystemInformation::SystemProcessorPerformanceInformation,
299+
data,
300+
(n_cpu * size_of::<SystemProcessorPerformanceInformation>()) as u32,
301+
std::ptr::null_mut(),
302+
);
303+
for i in 0..n_cpu {
304+
let cpu = data.add(i * size_of::<SystemProcessorPerformanceInformation>())
305+
as *const SystemProcessorPerformanceInformation;
306+
let cpu = cpu.as_ref().unwrap();
307+
cpu_load.idle_time += cpu.idle_time;
308+
cpu_load.kernel_time += cpu.kernel_time;
309+
cpu_load.user_time += cpu.user_time;
310+
cpu_load.dpc_time += cpu.dpc_time;
311+
cpu_load.interrupt_time += cpu.interrupt_time;
312+
cpu_load.interrupt_count += cpu.interrupt_count;
313+
}
314+
}
315+
let total = cpu_load.idle_time
316+
+ cpu_load.kernel_time
317+
+ cpu_load.user_time
318+
+ cpu_load.dpc_time
319+
+ cpu_load.interrupt_time;
305320
format!(
306-
"%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id",
307-
cpu.user * 100.0,
308-
cpu.system * 100.0,
309-
cpu.nice * 100.0,
310-
cpu.idle * 100.0
321+
"%Cpu(s): {:.1} us, {:.1} sy, {:.1} id, {:.1} hi, {:.1} si",
322+
cpu_load.user_time as f64 / total as f64 * 100.0,
323+
cpu_load.kernel_time as f64 / total as f64 * 100.0,
324+
cpu_load.idle_time as f64 / total as f64 * 100.0,
325+
cpu_load.interrupt_time as f64 / total as f64 * 100.0,
326+
cpu_load.dpc_time as f64 / total as f64 * 100.0,
311327
)
312328
}
313329

src/uu/top/src/top.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5555
// Must refresh twice.
5656
// https://docs.rs/sysinfo/0.31.2/sysinfo/struct.System.html#method.refresh_cpu_usage
5757
picker::sysinfo().write().unwrap().refresh_all();
58-
// Similar to the above.
59-
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
60-
crate::header::cpu_load();
6158
sleep(Duration::from_millis(200));
6259
picker::sysinfo().write().unwrap().refresh_all();
6360

0 commit comments

Comments
 (0)