44// file that was distributed with this source code.
55
66use crate :: picker:: sysinfo;
7+ use crate :: platform:: * ;
8+ use crate :: { CpuGraphMode , CpuValueMode , Settings } ;
79use bytesize:: ByteSize ;
10+ use uu_vmstat:: CpuLoad ;
811use uu_w:: get_formatted_uptime_procps;
912use uucore:: uptime:: { get_formatted_loadavg, get_formatted_nusers, get_formatted_time} ;
1013
11- pub ( crate ) fn header ( scale_summary_mem : Option < & String > ) -> String {
12- format ! (
13- "top - {time} {uptime}, {user}, {load_average}\n \
14- {task}\n \
15- {cpu}\n \
16- {memory}",
14+ pub ( crate ) fn header ( settings : & Settings ) -> String {
15+ let uptime_line = format ! (
16+ "top - {time} {uptime}, {user}, {load_average}\n " ,
1717 time = get_formatted_time( ) ,
1818 uptime = uptime( ) ,
1919 user = user( ) ,
2020 load_average = load_average( ) ,
21- task = task( ) ,
22- cpu = cpu( ) ,
23- memory = memory( scale_summary_mem) ,
24- )
25- }
21+ ) ;
22+
23+ let task_and_cpu = if settings. cpu_graph_mode == CpuGraphMode :: Hide {
24+ String :: new ( )
25+ } else {
26+ format ! (
27+ "{task}\n \
28+ {cpu}\n ",
29+ task = task( ) ,
30+ cpu = cpu( settings) ,
31+ )
32+ } ;
33+
34+ let memory_line = memory ( settings. scale_summary_mem . as_ref ( ) ) ;
2635
27- #[ cfg( target_os = "linux" ) ]
28- extern "C" {
29- pub fn sd_booted ( ) -> libc:: c_int ;
30- pub fn sd_get_sessions ( sessions : * mut * mut * mut libc:: c_char ) -> libc:: c_int ;
31- pub fn sd_session_get_class (
32- session : * const libc:: c_char ,
33- class : * mut * mut libc:: c_char ,
34- ) -> libc:: c_int ;
36+ format ! ( "{uptime_line}{task_and_cpu}{memory_line}" )
3537}
3638
3739fn format_memory ( memory_b : u64 , unit : u64 ) -> f64 {
@@ -43,53 +45,6 @@ fn uptime() -> String {
4345 get_formatted_uptime_procps ( ) . unwrap_or_default ( )
4446}
4547
46- #[ cfg( target_os = "linux" ) ]
47- pub fn get_nusers_systemd ( ) -> uucore:: error:: UResult < usize > {
48- use std:: ffi:: CStr ;
49- use std:: ptr;
50- use uucore:: error:: USimpleError ;
51- use uucore:: libc:: * ;
52-
53- // SAFETY: sd_booted to check if system is booted with systemd.
54- unsafe {
55- // systemd
56- if sd_booted ( ) > 0 {
57- let mut sessions_list: * mut * mut c_char = ptr:: null_mut ( ) ;
58- let mut num_user = 0 ;
59- let sessions = sd_get_sessions ( & mut sessions_list) ;
60-
61- if sessions > 0 {
62- for i in 0 ..sessions {
63- let mut class: * mut c_char = ptr:: null_mut ( ) ;
64-
65- if sd_session_get_class (
66- * sessions_list. add ( i as usize ) as * const c_char ,
67- & mut class,
68- ) < 0
69- {
70- continue ;
71- }
72- if CStr :: from_ptr ( class) . to_str ( ) . unwrap ( ) . starts_with ( "user" ) {
73- num_user += 1 ;
74- }
75- free ( class as * mut c_void ) ;
76- }
77- }
78-
79- for i in 0 ..sessions {
80- free ( * sessions_list. add ( i as usize ) as * mut c_void ) ;
81- }
82- free ( sessions_list as * mut c_void ) ;
83-
84- return Ok ( num_user) ;
85- }
86- }
87- Err ( USimpleError :: new (
88- 1 ,
89- "could not retrieve number of logged users" ,
90- ) )
91- }
92-
9348// see: https://gitlab.com/procps-ng/procps/-/blob/4740a0efa79cade867cfc7b32955fe0f75bf5173/library/uptime.c#L63-L115
9449fn user ( ) -> String {
9550 #[ cfg( target_os = "linux" ) ]
@@ -133,91 +88,84 @@ fn task() -> String {
13388 )
13489}
13590
136- #[ cfg( target_os = "linux" ) ]
137- fn cpu ( ) -> String {
138- let cpu_load = uu_vmstat:: CpuLoad :: current ( ) ;
91+ fn sum_cpu_loads ( cpu_loads : & [ uu_vmstat:: CpuLoadRaw ] ) -> uu_vmstat:: CpuLoadRaw {
92+ let mut total = uu_vmstat:: CpuLoadRaw {
93+ user : 0 ,
94+ nice : 0 ,
95+ system : 0 ,
96+ idle : 0 ,
97+ io_wait : 0 ,
98+ hardware_interrupt : 0 ,
99+ software_interrupt : 0 ,
100+ steal_time : 0 ,
101+ guest : 0 ,
102+ guest_nice : 0 ,
103+ } ;
139104
140- format ! (
141- "%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa, {:.1} hi, {:.1} si, {:.1} st" ,
142- cpu_load. user,
143- cpu_load. system,
144- cpu_load. nice,
145- cpu_load. idle,
146- cpu_load. io_wait,
147- cpu_load. hardware_interrupt,
148- cpu_load. software_interrupt,
149- cpu_load. steal_time,
150- )
105+ for load in cpu_loads {
106+ total. user += load. user ;
107+ total. nice += load. nice ;
108+ total. system += load. system ;
109+ total. idle += load. idle ;
110+ total. io_wait += load. io_wait ;
111+ total. hardware_interrupt += load. hardware_interrupt ;
112+ total. software_interrupt += load. software_interrupt ;
113+ total. steal_time += load. steal_time ;
114+ total. guest += load. guest ;
115+ total. guest_nice += load. guest_nice ;
116+ }
117+
118+ total
151119}
152120
153- #[ cfg( target_os = "windows" ) ]
154- fn cpu ( ) -> String {
155- use libc:: malloc;
156- use windows_sys:: Wdk :: System :: SystemInformation :: NtQuerySystemInformation ;
157-
158- #[ repr( C ) ]
159- #[ derive( Debug ) ]
160- struct SystemProcessorPerformanceInformation {
161- idle_time : i64 , // LARGE_INTEGER
162- kernel_time : i64 , // LARGE_INTEGER
163- user_time : i64 , // LARGE_INTEGER
164- dpc_time : i64 , // LARGE_INTEGER
165- interrupt_time : i64 , // LARGE_INTEGER
166- interrupt_count : u32 , // ULONG
121+ fn cpu ( settings : & Settings ) -> String {
122+ if settings. cpu_graph_mode == CpuGraphMode :: Hide {
123+ return String :: new ( ) ;
167124 }
168125
169- let n_cpu = sysinfo ( ) . read ( ) . unwrap ( ) . cpus ( ) . len ( ) ;
170- let mut cpu_load = SystemProcessorPerformanceInformation {
171- idle_time : 0 ,
172- kernel_time : 0 ,
173- user_time : 0 ,
174- dpc_time : 0 ,
175- interrupt_time : 0 ,
176- interrupt_count : 0 ,
177- } ;
178- // SAFETY: malloc is safe to use here. We free the memory after we are done with it. If action fails, all "time" will be 0.
179- unsafe {
180- let len = n_cpu * size_of :: < SystemProcessorPerformanceInformation > ( ) ;
181- let data = malloc ( len) ;
182- let status = NtQuerySystemInformation (
183- windows_sys:: Wdk :: System :: SystemInformation :: SystemProcessorPerformanceInformation ,
184- data,
185- ( n_cpu * size_of :: < SystemProcessorPerformanceInformation > ( ) ) as u32 ,
186- std:: ptr:: null_mut ( ) ,
187- ) ;
188- if status == 0 {
189- for i in 0 ..n_cpu {
190- let cpu = data. add ( i * size_of :: < SystemProcessorPerformanceInformation > ( ) )
191- as * const SystemProcessorPerformanceInformation ;
192- let cpu = cpu. as_ref ( ) . unwrap ( ) ;
193- cpu_load. idle_time += cpu. idle_time ;
194- cpu_load. kernel_time += cpu. kernel_time ;
195- cpu_load. user_time += cpu. user_time ;
196- cpu_load. dpc_time += cpu. dpc_time ;
197- cpu_load. interrupt_time += cpu. interrupt_time ;
198- cpu_load. interrupt_count += cpu. interrupt_count ;
199- }
126+ let cpu_loads = get_cpu_loads ( ) ;
127+
128+ match settings. cpu_value_mode {
129+ CpuValueMode :: PerCore => {
130+ let lines = cpu_loads
131+ . iter ( )
132+ . enumerate ( )
133+ . map ( |( nth, cpu_load_raw) | {
134+ let cpu_load = CpuLoad :: from_raw ( cpu_load_raw) ;
135+ cpu_line ( format ! ( "Cpu{nth}" ) . as_str ( ) , & cpu_load, settings)
136+ } )
137+ . collect :: < Vec < String > > ( ) ;
138+ lines. join ( "\n " )
139+ }
140+ CpuValueMode :: Sum => {
141+ let total = sum_cpu_loads ( & cpu_loads) ;
142+ let cpu_load = CpuLoad :: from_raw ( & total) ;
143+ cpu_line ( "Cpu" , & cpu_load, settings)
200144 }
201145 }
202- let total = cpu_load. idle_time
203- + cpu_load. kernel_time
204- + cpu_load. user_time
205- + cpu_load. dpc_time
206- + cpu_load. interrupt_time ;
207- format ! (
208- "%Cpu(s): {:.1} us, {:.1} sy, {:.1} id, {:.1} hi, {:.1} si" ,
209- cpu_load. user_time as f64 / total as f64 * 100.0 ,
210- cpu_load. kernel_time as f64 / total as f64 * 100.0 ,
211- cpu_load. idle_time as f64 / total as f64 * 100.0 ,
212- cpu_load. interrupt_time as f64 / total as f64 * 100.0 ,
213- cpu_load. dpc_time as f64 / total as f64 * 100.0 ,
214- )
215146}
216147
217- //TODO: Implement for macos
218- #[ cfg( target_os = "macos" ) ]
219- fn cpu ( ) -> String {
220- "TODO" . into ( )
148+ fn cpu_line ( tag : & str , cpu_load : & CpuLoad , settings : & Settings ) -> String {
149+ if settings. cpu_graph_mode == CpuGraphMode :: Hide {
150+ return String :: new ( ) ;
151+ }
152+
153+ if settings. cpu_graph_mode == CpuGraphMode :: Sum {
154+ return format ! (
155+ "%{tag:<6}: {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa, {:.1} hi, {:.1} si, {:.1} st" ,
156+ cpu_load. user,
157+ cpu_load. system,
158+ cpu_load. nice,
159+ cpu_load. idle,
160+ cpu_load. io_wait,
161+ cpu_load. hardware_interrupt,
162+ cpu_load. software_interrupt,
163+ cpu_load. steal_time,
164+ ) ;
165+ }
166+
167+ // TODO: render colored bar chart or block chart
168+ format ! ( "%{tag:<6}: {:>5.1}/{:<5.1}" , cpu_load. user, cpu_load. system)
221169}
222170
223171fn memory ( scale_summary_mem : Option < & String > ) -> String {
0 commit comments