1 //! https://github.com/gperftools/gperftools
7 sync::atomic::{AtomicUsize, Ordering},
10 #[link(name = "profiler")]
11 #[allow(non_snake_case)]
13 fn ProfilerStart(fname: *const c_char) -> i32;
19 const PENDING: usize = 2;
21 fn transition(current: usize, new: usize) -> bool {
22 static STATE: AtomicUsize = AtomicUsize::new(OFF);
24 STATE.compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst).is_ok()
27 pub(crate) fn start(path: &Path) {
28 if !transition(OFF, PENDING) {
29 panic!("profiler already started");
31 let path = CString::new(path.display().to_string()).unwrap();
32 if unsafe { ProfilerStart(path.as_ptr()) } == 0 {
33 panic!("profiler failed to start")
35 assert!(transition(PENDING, ON));
38 pub(crate) fn stop() {
39 if !transition(ON, PENDING) {
40 panic!("profiler is not started")
42 unsafe { ProfilerStop() };
43 assert!(transition(PENDING, OFF));