11use std:: { io, ptr, mem:: { self , MaybeUninit } , ffi, slice} ;
22use libc:: {
3- c_int, c_void, host_statistics64, mach_host_self, size_t, statfs, sysconf, sysctl,
4- sysctlnametomib, timeval, vm_statistics64, xsw_usage, CTL_VM , HOST_VM_INFO64 ,
5- HOST_VM_INFO64_COUNT , KERN_SUCCESS , VM_SWAPUSAGE , _SC_PHYS_PAGES,
3+ c_int, c_void, host_processor_info, host_statistics64, mach_msg_type_number_t,
4+ natural_t, processor_cpu_load_info, processor_info_array_t, size_t, statfs,
5+ sysconf, sysctl, sysctlnametomib, timeval, vm_address_t, vm_deallocate, vm_size_t,
6+ vm_statistics64, xsw_usage, CTL_VM , CPU_STATE_IDLE , CPU_STATE_NICE , CPU_STATE_SYSTEM ,
7+ CPU_STATE_USER , HOST_VM_INFO64 , HOST_VM_INFO64_COUNT , KERN_SUCCESS ,
8+ PROCESSOR_CPU_LOAD_INFO , VM_SWAPUSAGE , _SC_PHYS_PAGES,
69} ;
10+ use mach2:: mach_init:: mach_host_self;
11+ use mach2:: traps:: mach_task_self;
712use crate :: data:: * ;
813use super :: common:: * ;
914use super :: unix;
@@ -30,7 +35,7 @@ macro_rules! sysctl {
3035 let mut size = $size;
3136 if unsafe { sysctl( & mib[ 0 ] as * const _ as * mut _, mib. len( ) as u32 ,
3237 $dataptr as * mut _ as * mut c_void, & mut size, ptr:: null_mut( ) , 0 ) } != 0 && $shouldcheck {
33- return Err ( io:: Error :: new ( io :: ErrorKind :: Other , "sysctl() failed" ) )
38+ return Err ( io:: Error :: other ( "sysctl() failed" ) )
3439 }
3540 size
3641 }
@@ -53,7 +58,12 @@ impl Platform for PlatformImpl {
5358 }
5459
5560 fn cpu_load ( & self ) -> io:: Result < DelayedMeasurement < Vec < CPULoad > > > {
56- Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Not supported" ) )
61+ let loads = measure_cpu ( ) ?;
62+ Ok ( DelayedMeasurement :: new (
63+ Box :: new ( move || Ok ( loads. iter ( )
64+ . zip ( measure_cpu ( ) ?. iter ( ) )
65+ . map ( |( prev, now) | ( * now - prev) . to_cpuload ( ) )
66+ . collect :: < Vec < _ > > ( ) ) ) ) )
5767 }
5868
5969 fn load_average ( & self ) -> io:: Result < LoadAverage > {
@@ -64,10 +74,7 @@ impl Platform for PlatformImpl {
6474 // Get Total Memory
6575 let total = match unsafe { sysconf ( _SC_PHYS_PAGES) } {
6676 -1 => {
67- return Err ( io:: Error :: new (
68- io:: ErrorKind :: Other ,
69- "sysconf(_SC_PHYS_PAGES) failed" ,
70- ) )
77+ return Err ( io:: Error :: other ( "sysconf(_SC_PHYS_PAGES) failed" ) )
7178 }
7279 n => n as u64 ,
7380 } ;
@@ -87,10 +94,7 @@ impl Platform for PlatformImpl {
8794 } ;
8895
8996 if ret != KERN_SUCCESS {
90- return Err ( io:: Error :: new (
91- io:: ErrorKind :: Other ,
92- "host_statistics64() failed" ,
93- ) ) ;
97+ return Err ( io:: Error :: other ( "host_statistics64() failed" ) ) ;
9498 }
9599 let stat = unsafe { stat. assume_init ( ) } ;
96100
@@ -107,7 +111,7 @@ impl Platform for PlatformImpl {
107111 external : ByteSize :: kib ( ( stat. external_page_count as u64 ) << * bsd:: PAGESHIFT ) ,
108112 internal : ByteSize :: kib ( ( stat. internal_page_count as u64 ) << * bsd:: PAGESHIFT ) ,
109113 uncompressed_in_compressor : ByteSize :: kib (
110- ( stat. total_uncompressed_pages_in_compressor as u64 ) << * bsd:: PAGESHIFT ,
114+ stat. total_uncompressed_pages_in_compressor << * bsd:: PAGESHIFT ,
111115 ) ,
112116 } ;
113117
@@ -143,49 +147,96 @@ impl Platform for PlatformImpl {
143147 fn boot_time ( & self ) -> io:: Result < OffsetDateTime > {
144148 let mut data: timeval = unsafe { mem:: zeroed ( ) } ;
145149 sysctl ! ( KERN_BOOTTIME , & mut data, mem:: size_of:: <timeval>( ) ) ;
146- let ts = OffsetDateTime :: from_unix_timestamp ( data. tv_sec . into ( ) ) . expect ( "unix timestamp should be within range" ) + Duration :: from_nanos ( data. tv_usec as u64 ) ;
150+ let ts = OffsetDateTime :: from_unix_timestamp ( data. tv_sec ) . expect ( "unix timestamp should be within range" ) + Duration :: from_nanos ( data. tv_usec as u64 ) ;
147151 Ok ( ts)
148152 }
149153
150154 fn battery_life ( & self ) -> io:: Result < BatteryLife > {
151- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
155+ Err ( io:: Error :: other ( "Not supported" ) )
152156 }
153157
154158 fn on_ac_power ( & self ) -> io:: Result < bool > {
155- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
159+ Err ( io:: Error :: other ( "Not supported" ) )
156160 }
157161
158162 fn mounts ( & self ) -> io:: Result < Vec < Filesystem > > {
159163 let mut mptr: * mut statfs = ptr:: null_mut ( ) ;
160164 let len = unsafe { getmntinfo ( & mut mptr, 2_i32 ) } ;
161165 if len < 1 {
162- return Err ( io:: Error :: new ( io :: ErrorKind :: Other , "getmntinfo() failed" ) )
166+ return Err ( io:: Error :: other ( "getmntinfo() failed" ) )
163167 }
164168 let mounts = unsafe { slice:: from_raw_parts ( mptr, len as usize ) } ;
165169 Ok ( mounts. iter ( ) . map ( statfs_to_fs) . collect :: < Vec < _ > > ( ) )
166170 }
167171
168172 fn block_device_statistics ( & self ) -> io:: Result < BTreeMap < String , BlockDeviceStats > > {
169- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
173+ Err ( io:: Error :: other ( "Not supported" ) )
170174 }
171175
172176 fn networks ( & self ) -> io:: Result < BTreeMap < String , Network > > {
173177 unix:: networks ( )
174178 }
175179
176180 fn network_stats ( & self , _interface : & str ) -> io:: Result < NetworkStats > {
177- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
181+ Err ( io:: Error :: other ( "Not supported" ) )
178182 }
179183
180184 fn cpu_temp ( & self ) -> io:: Result < f32 > {
181- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
185+ Err ( io:: Error :: other ( "Not supported" ) )
182186 }
183187
184188 fn socket_stats ( & self ) -> io:: Result < SocketStats > {
185- Err ( io:: Error :: new ( io :: ErrorKind :: Other , "Not supported" ) )
189+ Err ( io:: Error :: other ( "Not supported" ) )
186190 }
187191}
188192
193+ fn measure_cpu ( ) -> io:: Result < Vec < CpuTime > > {
194+ let mut num_cpus: natural_t = 0 ;
195+ let mut info: processor_info_array_t = ptr:: null_mut ( ) ;
196+ let mut info_count: mach_msg_type_number_t = 0 ;
197+
198+ let ret = unsafe {
199+ host_processor_info (
200+ mach_host_self ( ) ,
201+ PROCESSOR_CPU_LOAD_INFO ,
202+ & mut num_cpus,
203+ & mut info,
204+ & mut info_count,
205+ )
206+ } ;
207+
208+ if ret != KERN_SUCCESS {
209+ return Err ( io:: Error :: other ( "host_processor_info() failed" ) ) ;
210+ }
211+
212+ let loads = unsafe {
213+ let cpus = slice:: from_raw_parts (
214+ info as * const processor_cpu_load_info ,
215+ num_cpus as usize ,
216+ ) ;
217+ cpus. iter ( )
218+ . map ( |cpu| CpuTime {
219+ user : cpu. cpu_ticks [ CPU_STATE_USER as usize ] as usize ,
220+ nice : cpu. cpu_ticks [ CPU_STATE_NICE as usize ] as usize ,
221+ system : cpu. cpu_ticks [ CPU_STATE_SYSTEM as usize ] as usize ,
222+ interrupt : 0 ,
223+ idle : cpu. cpu_ticks [ CPU_STATE_IDLE as usize ] as usize ,
224+ other : 0 ,
225+ } )
226+ . collect :: < Vec < _ > > ( )
227+ } ;
228+
229+ unsafe {
230+ vm_deallocate (
231+ mach_task_self ( ) ,
232+ info as vm_address_t ,
233+ info_count as vm_size_t * mem:: size_of :: < natural_t > ( ) as vm_size_t ,
234+ ) ;
235+ }
236+
237+ Ok ( loads)
238+ }
239+
189240fn statfs_to_fs ( x : & statfs ) -> Filesystem {
190241 Filesystem {
191242 files : ( x. f_files as usize ) . saturating_sub ( x. f_ffree as usize ) ,
0 commit comments