Skip to content

Commit 5093892

Browse files
committed
top: cpu time for windows
1 parent b7f8e7c commit 5093892

File tree

3 files changed

+57
-44
lines changed

3 files changed

+57
-44
lines changed

src/uu/top/Cargo.toml

+1-1
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

+56-40
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!(
@@ -296,16 +264,64 @@ fn cpu() -> String {
296264
)
297265
}
298266

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

src/uu/top/src/top.rs

-3
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)