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 thread_handle_for_allocations(&self) -> Option<ThreadHandle> {
36        self.threads.first().cloned()
37    }
38
39    pub fn set_start_time(&mut self, start_time: Timestamp) {
40        self.start_time = start_time;
41    }
42
43    pub fn start_time(&self) -> Timestamp {
44        self.start_time
45    }
46
47    pub fn set_end_time(&mut self, end_time: Timestamp) {
48        self.end_time = Some(end_time);
49    }
50
51    pub fn end_time(&self) -> Option<Timestamp> {
52        self.end_time
53    }
54
55    pub fn set_name(&mut self, name: &str) {
56        self.name = name.to_string();
57    }
58
59    pub fn name(&self) -> &str {
60        &self.name
61    }
62
63    pub fn add_thread(&mut self, thread: ThreadHandle) {
64        self.threads.push(thread);
65    }
66
67    pub fn pid(&self) -> &str {
68        &self.pid
69    }
70
71    pub fn cmp_for_json_order(&self, other: &Process) -> Ordering {
72        if let Some(ordering) = self.start_time.partial_cmp(&other.start_time) {
73            if ordering != Ordering::Equal {
74                return ordering;
75            }
76        }
77        self.pid.cmp(&other.pid)
78    }
79
80    pub fn threads(&self) -> &[ThreadHandle] {
81        &self.threads
82    }
83
84    pub fn convert_address(
85        &mut self,
86        global_libs: &mut GlobalLibTable,
87        kernel_libs: &mut LibMappings<LibraryHandle>,
88        address: u64,
89    ) -> InternalFrameLocation {
90        // Try to find the address in the kernel libs first, and then in the process libs.
91        match kernel_libs
92            .convert_address(address)
93            .or_else(|| self.libs.convert_address(address))
94        {
95            Some((relative_address, lib_handle)) => {
96                let global_lib_index = global_libs.index_for_used_lib(*lib_handle);
97                InternalFrameLocation::AddressInLib(relative_address, global_lib_index)
98            }
99            None => InternalFrameLocation::UnknownAddress(address),
100        }
101    }
102
103    pub fn add_lib_mapping(
104        &mut self,
105        lib: LibraryHandle,
106        start_avma: u64,
107        end_avma: u64,
108        relative_address_at_start: u32,
109    ) {
110        self.libs
111            .add_mapping(start_avma, end_avma, relative_address_at_start, lib);
112    }
113
114    pub fn remove_lib_mapping(&mut self, start_avma: u64) {
115        self.libs.remove_mapping(start_avma);
116    }
117
118    pub fn remove_all_lib_mappings(&mut self) {
119        self.libs.clear();
120    }
121}