]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/profile/src/google_cpu_profiler.rs
Auto merge of #99680 - workingjubilee:revert-revert-icf, r=Mark-Simulacrum
[rust.git] / src / tools / rust-analyzer / crates / profile / src / google_cpu_profiler.rs
1 //! https://github.com/gperftools/gperftools
2
3 use std::{
4     ffi::CString,
5     os::raw::c_char,
6     path::Path,
7     sync::atomic::{AtomicUsize, Ordering},
8 };
9
10 #[link(name = "profiler")]
11 #[allow(non_snake_case)]
12 extern "C" {
13     fn ProfilerStart(fname: *const c_char) -> i32;
14     fn ProfilerStop();
15 }
16
17 const OFF: usize = 0;
18 const ON: usize = 1;
19 const PENDING: usize = 2;
20
21 fn transition(current: usize, new: usize) -> bool {
22     static STATE: AtomicUsize = AtomicUsize::new(OFF);
23
24     STATE.compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst).is_ok()
25 }
26
27 pub(crate) fn start(path: &Path) {
28     if !transition(OFF, PENDING) {
29         panic!("profiler already started");
30     }
31     let path = CString::new(path.display().to_string()).unwrap();
32     if unsafe { ProfilerStart(path.as_ptr()) } == 0 {
33         panic!("profiler failed to start")
34     }
35     assert!(transition(PENDING, ON));
36 }
37
38 pub(crate) fn stop() {
39     if !transition(ON, PENDING) {
40         panic!("profiler is not started")
41     }
42     unsafe { ProfilerStop() };
43     assert!(transition(PENDING, OFF));
44 }