]> git.proxmox.com Git - rustc.git/blame - vendor/sysinfo/src/freebsd/process.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / vendor / sysinfo / src / freebsd / process.rs
CommitLineData
923072b8
FG
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::{DiskUsage, Gid, Pid, ProcessExt, ProcessRefreshKind, ProcessStatus, Signal, Uid};
4
5use std::fmt;
6use std::path::{Path, PathBuf};
7
8use super::utils::{get_sys_value_str, WrapMap};
9
10#[doc(hidden)]
11impl From<libc::c_char> for ProcessStatus {
12 fn from(status: libc::c_char) -> ProcessStatus {
13 match status {
14 libc::SIDL => ProcessStatus::Idle,
15 libc::SRUN => ProcessStatus::Run,
16 libc::SSLEEP => ProcessStatus::Sleep,
17 libc::SSTOP => ProcessStatus::Stop,
18 libc::SZOMB => ProcessStatus::Zombie,
19 libc::SWAIT => ProcessStatus::Dead,
20 libc::SLOCK => ProcessStatus::LockBlocked,
21 x => ProcessStatus::Unknown(x as _),
22 }
23 }
24}
25
26impl fmt::Display for ProcessStatus {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 f.write_str(match *self {
29 ProcessStatus::Idle => "Idle",
30 ProcessStatus::Run => "Runnable",
31 ProcessStatus::Sleep => "Sleeping",
32 ProcessStatus::Stop => "Stopped",
33 ProcessStatus::Zombie => "Zombie",
34 ProcessStatus::Dead => "Dead",
35 ProcessStatus::LockBlocked => "LockBlocked",
36 _ => "Unknown",
37 })
38 }
39}
40
41#[doc = include_str!("../../md_doc/process.md")]
42pub struct Process {
43 pub(crate) name: String,
44 pub(crate) cmd: Vec<String>,
45 pub(crate) exe: PathBuf,
46 pub(crate) pid: Pid,
47 parent: Option<Pid>,
48 pub(crate) environ: Vec<String>,
49 pub(crate) cwd: PathBuf,
50 pub(crate) root: PathBuf,
51 pub(crate) memory: u64,
52 pub(crate) virtual_memory: u64,
53 pub(crate) updated: bool,
54 cpu_usage: f32,
55 start_time: u64,
56 run_time: u64,
57 pub(crate) status: ProcessStatus,
58 user_id: Uid,
59 group_id: Gid,
60 read_bytes: u64,
61 old_read_bytes: u64,
62 written_bytes: u64,
63 old_written_bytes: u64,
64}
65
66impl ProcessExt for Process {
67 fn kill_with(&self, signal: Signal) -> Option<bool> {
68 let c_signal = super::system::convert_signal(signal)?;
69 unsafe { Some(libc::kill(self.pid.0, c_signal) == 0) }
70 }
71
72 fn name(&self) -> &str {
73 &self.name
74 }
75
76 fn cmd(&self) -> &[String] {
77 &self.cmd
78 }
79
80 fn exe(&self) -> &Path {
81 self.exe.as_path()
82 }
83
84 fn pid(&self) -> Pid {
85 self.pid
86 }
87
88 fn environ(&self) -> &[String] {
89 &self.environ
90 }
91
92 fn cwd(&self) -> &Path {
93 self.cwd.as_path()
94 }
95
96 fn root(&self) -> &Path {
97 self.root.as_path()
98 }
99
100 fn memory(&self) -> u64 {
101 self.memory
102 }
103
104 fn virtual_memory(&self) -> u64 {
105 self.virtual_memory
106 }
107
108 fn parent(&self) -> Option<Pid> {
109 self.parent
110 }
111
112 fn status(&self) -> ProcessStatus {
113 self.status
114 }
115
116 fn start_time(&self) -> u64 {
117 self.start_time
118 }
119
120 fn run_time(&self) -> u64 {
121 self.run_time
122 }
123
124 fn cpu_usage(&self) -> f32 {
125 self.cpu_usage
126 }
127
128 fn disk_usage(&self) -> DiskUsage {
129 DiskUsage {
130 written_bytes: self.written_bytes.saturating_sub(self.old_written_bytes),
131 total_written_bytes: self.written_bytes,
132 read_bytes: self.read_bytes.saturating_sub(self.old_read_bytes),
133 total_read_bytes: self.read_bytes,
134 }
135 }
136
137 fn user_id(&self) -> Option<&Uid> {
138 Some(&self.user_id)
139 }
140
141 fn group_id(&self) -> Option<Gid> {
142 Some(self.group_id)
143 }
144}
145
146pub(crate) unsafe fn get_process_data(
147 kproc: &libc::kinfo_proc,
148 wrap: &WrapMap,
149 page_size: isize,
150 fscale: f32,
151 now: u64,
152 refresh_kind: ProcessRefreshKind,
153) -> Result<Option<Process>, ()> {
154 if kproc.ki_pid != 1 && (kproc.ki_flag as libc::c_int & libc::P_SYSTEM) != 0 {
155 // We filter out the kernel threads.
156 return Err(());
157 }
158
159 // We now get the values needed for both new and existing process.
160 let cpu_usage = if refresh_kind.cpu() {
161 (100 * kproc.ki_pctcpu) as f32 / fscale
162 } else {
163 0.
164 };
165 // Processes can be reparented apparently?
166 let parent = if kproc.ki_ppid != 0 {
167 Some(Pid(kproc.ki_ppid))
168 } else {
169 None
170 };
171 let status = ProcessStatus::from(kproc.ki_stat);
172
173 // from FreeBSD source /src/usr.bin/top/machine.c
174 let virtual_memory = (kproc.ki_size / 1_000) as u64;
175 let memory = (kproc.ki_rssize as u64).saturating_mul(page_size as _) / 1_000;
176 // FIXME: This is to get the "real" run time (in micro-seconds).
177 // let run_time = (kproc.ki_runtime + 5_000) / 10_000;
178
179 if let Some(proc_) = (*wrap.0.get()).get_mut(&Pid(kproc.ki_pid)) {
180 proc_.cpu_usage = cpu_usage;
181 proc_.parent = parent;
182 proc_.status = status;
183 proc_.virtual_memory = virtual_memory;
184 proc_.memory = memory;
185 proc_.run_time = now.saturating_sub(proc_.start_time);
186 proc_.updated = true;
187
188 if refresh_kind.disk_usage() {
189 proc_.old_read_bytes = proc_.read_bytes;
190 proc_.read_bytes = kproc.ki_rusage.ru_inblock as _;
191 proc_.old_written_bytes = proc_.written_bytes;
192 proc_.written_bytes = kproc.ki_rusage.ru_oublock as _;
193 }
194
195 return Ok(None);
196 }
197
198 // This is a new process, we need to get more information!
199 let mut buffer = [0; libc::PATH_MAX as usize + 1];
200
201 let exe = get_sys_value_str(
202 &[
203 libc::CTL_KERN,
204 libc::KERN_PROC,
205 libc::KERN_PROC_PATHNAME,
206 kproc.ki_pid,
207 ],
208 &mut buffer,
209 )
210 .unwrap_or_default();
211 // For some reason, it can return completely invalid path like `p\u{5}`. So we need to use
212 // procstat to get around this problem.
213 // let cwd = get_sys_value_str(
214 // &[
215 // libc::CTL_KERN,
216 // libc::KERN_PROC,
217 // libc::KERN_PROC_CWD,
218 // kproc.ki_pid,
219 // ],
220 // &mut buffer,
221 // )
222 // .map(|s| s.into())
223 // .unwrap_or_else(PathBuf::new);
224
225 let start_time = kproc.ki_start.tv_sec as u64;
226 Ok(Some(Process {
227 pid: Pid(kproc.ki_pid),
228 parent,
229 user_id: Uid(kproc.ki_ruid),
230 group_id: Gid(kproc.ki_rgid),
231 start_time,
232 run_time: now.saturating_sub(start_time),
233 cpu_usage,
234 virtual_memory,
235 memory,
236 // procstat_getfiles
237 cwd: PathBuf::new(),
238 exe: exe.into(),
239 // kvm_getargv isn't thread-safe so we get it in the main thread.
240 name: String::new(),
241 // kvm_getargv isn't thread-safe so we get it in the main thread.
242 cmd: Vec::new(),
243 // kvm_getargv isn't thread-safe so we get it in the main thread.
244 root: PathBuf::new(),
245 // kvm_getenvv isn't thread-safe so we get it in the main thread.
246 environ: Vec::new(),
247 status,
248 read_bytes: kproc.ki_rusage.ru_inblock as _,
249 old_read_bytes: 0,
250 written_bytes: kproc.ki_rusage.ru_oublock as _,
251 old_written_bytes: 0,
252 updated: true,
253 }))
254}