fxprof_processed_profile/
process.rs

1use std::cmp::Ordering;
2use std::hash::Hash;
3
4use crate::frame_table::InternalFrameLocation;
5use crate::global_lib_table::{GlobalLibTable, LibraryHandle};
6use crate::lib_mappings::LibMappings;
7use crate::Timestamp;
8
9/// A thread. Can be created with [`Profile::add_thread`](crate::Profile::add_thread).
10#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
11pub struct ThreadHandle(pub(crate) usize);
12
13#[derive(Debug)]
14pub struct Process {
15    pid: String,
16    name: String,
17    threads: Vec<ThreadHandle>,
18    start_time: Timestamp,
19    end_time: Option<Timestamp>,
20    libs: LibMappings<LibraryHandle>,
21}
22
23impl Process {
24    pub fn new(name: &str, pid: String, start_time: Timestamp) -> Self {
25        Self {
26            pid,
27            threads: Vec::new(),
28            libs: LibMappings::new(),
29            start_time,
30            end_time: None,
31            name: name.to_owned(),
32        }
33    }
34
35    pub fn set_start_time(&mut self, start_time: Timestamp) {
36        self.start_time = start_time;
37    }
38
39    pub fn start_time(&self) -> Timestamp {
40        self.start_time
41    }
42
43    pub fn set_end_time(&mut self, end_time: Timestamp) {
44        self.end_time = Some(end_time);
45    }
46
47    pub fn end_time(&self) -> Option<Timestamp> {
48        self.end_time
49    }
50
51    pub fn set_name(&mut self, name: &str) {
52        self.name = name.to_string();
53    }
54
55    pub fn name(&self) -> &str {
56        &self.name
57    }
58
59    pub fn add_thread(&mut self, thread: ThreadHandle) {
60        self.threads.push(thread);
61    }
62
63    pub fn pid(&self) -> &str {
64        &self.pid
65    }
66
67    pub fn cmp_for_json_order(&self, other: &Process) -> Ordering {
68        if let Some(ordering) = self.start_time.partial_cmp(&other.start_time) {
69            if ordering != Ordering::Equal {
70                return ordering;
71            }
72        }
73        self.pid.cmp(&other.pid)
74    }
75
76    pub fn threads(&self) -> &[ThreadHandle] {
77        &self.threads
78    }
79
80    pub fn convert_address(
81        &mut self,
82        global_libs: &mut GlobalLibTable,
83        kernel_libs: &mut LibMappings<LibraryHandle>,
84        address: u64,
85    ) -> InternalFrameLocation {
86        // Try to find the address in the kernel libs first, and then in the process libs.
87        match kernel_libs
88            .convert_address(address)
89            .or_else(|| self.libs.convert_address(address))
90        {
91            Some((relative_address, lib_handle)) => {
92                let global_lib_index = global_libs.index_for_used_lib(*lib_handle);
93                InternalFrameLocation::AddressInLib(relative_address, global_lib_index)
94            }
95            None => InternalFrameLocation::UnknownAddress(address),
96        }
97    }
98
99    pub fn add_lib_mapping(
100        &mut self,
101        lib: LibraryHandle,
102        start_avma: u64,
103        end_avma: u64,
104        relative_address_at_start: u32,
105    ) {
106        self.libs
107            .add_mapping(start_avma, end_avma, relative_address_at_start, lib);
108    }
109
110    pub fn remove_lib_mapping(&mut self, start_avma: u64) {
111        self.libs.remove_mapping(start_avma);
112    }
113
114    pub fn remove_all_lib_mappings(&mut self) {
115        self.libs.clear();
116    }
117}