diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/measureme/src/raw_event.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/measureme/src/raw_event.rs')
-rw-r--r-- | vendor/measureme/src/raw_event.rs | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/vendor/measureme/src/raw_event.rs b/vendor/measureme/src/raw_event.rs new file mode 100644 index 000000000..f181fb56f --- /dev/null +++ b/vendor/measureme/src/raw_event.rs @@ -0,0 +1,409 @@ +use crate::event_id::EventId; +use crate::stringtable::StringId; +#[cfg(target_endian = "big")] +use std::convert::TryInto; + +/// `RawEvent` is how events are stored on-disk. If you change this struct, +/// make sure that you increment `file_header::CURRENT_FILE_FORMAT_VERSION`. +#[derive(Eq, PartialEq, Debug)] +#[repr(C)] +pub struct RawEvent { + pub event_kind: StringId, + pub event_id: EventId, + pub thread_id: u32, + + // The following 96 bits store the payload values, using + // 48 bits for each. + // Interval: + // Payload 1 is start value and payload 2 is end value + // SSSSSSSSSSSSSSSSEEEEEEEEEEEEEEEESSSSSSSEEEEEEEEE + // [payload1_lower][payload2_lower][payloads_upper] + // Instant: + // Payload2 is 0xFFFF_FFFF_FFFF + // VVVVVVVVVVVVVVVV1111111111111111VVVVVVV11111111 + // [payload1_lower][payload2_lower][payloads_upper] + // Integer: + // Payload2 is 0xFFFF_FFFF_FFFE + // VVVVVVVVVVVVVVVV1111111111111111VVVVVVV11111110 + // [payload1_lower][payload2_lower][payloads_upper] + pub payload1_lower: u32, + pub payload2_lower: u32, + pub payloads_upper: u32, +} + +/// `RawEvents` that have a payload 2 value with this value are instant events. +const INSTANT_MARKER: u64 = 0xFFFF_FFFF_FFFF; +/// `RawEvents` that have a payload 2 value with this value are integer events. +const INTEGER_MARKER: u64 = INSTANT_MARKER - 1; + +/// The max value we can represent with the 48 bits available. +pub const MAX_SINGLE_VALUE: u64 = 0xFFFF_FFFF_FFFF; + +/// The max value we can represent with the 48 bits available. +/// The highest two values are reserved for the `INSTANT_MARKER` and `INTEGER_MARKER`. +pub const MAX_INTERVAL_VALUE: u64 = INTEGER_MARKER - 1; + +impl RawEvent { + #[inline] + pub fn new_interval( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + start: u64, + end: u64, + ) -> Self { + assert!(start <= end); + assert!(end <= MAX_INTERVAL_VALUE); + + Self::pack_values(event_kind, event_id, thread_id, start, end) + } + + #[inline] + pub fn new_instant( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + instant: u64, + ) -> Self { + assert!(instant <= MAX_SINGLE_VALUE); + Self::pack_values(event_kind, event_id, thread_id, instant, INSTANT_MARKER) + } + + #[inline] + pub fn new_integer( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + value: u64, + ) -> Self { + assert!(value <= MAX_SINGLE_VALUE); + Self::pack_values(event_kind, event_id, thread_id, value, INTEGER_MARKER) + } + + #[inline] + fn pack_values( + event_kind: StringId, + event_id: EventId, + thread_id: u32, + value1: u64, + value2: u64, + ) -> Self { + let payload1_lower = value1 as u32; + let payload2_lower = value2 as u32; + + let value1_upper = (value1 >> 16) as u32 & 0xFFFF_0000; + let value2_upper = (value2 >> 32) as u32; + + let payloads_upper = value1_upper | value2_upper; + + Self { + event_kind, + event_id, + thread_id, + payload1_lower, + payload2_lower, + payloads_upper, + } + } + + /// The start value assuming self is an interval + #[inline] + pub fn start_value(&self) -> u64 { + self.payload1_lower as u64 | (((self.payloads_upper & 0xFFFF_0000) as u64) << 16) + } + + /// The end value assuming self is an interval + #[inline] + pub fn end_value(&self) -> u64 { + self.payload2_lower as u64 | (((self.payloads_upper & 0x0000_FFFF) as u64) << 32) + } + + /// The value assuming self is an interval or integer. + #[inline] + pub fn value(&self) -> u64 { + self.payload1_lower as u64 | (((self.payloads_upper & 0xFFFF_0000) as u64) << 16) + } + + #[inline] + pub fn is_instant(&self) -> bool { + self.end_value() == INSTANT_MARKER + } + + #[inline] + pub fn is_integer(&self) -> bool { + self.end_value() == INTEGER_MARKER + } + + #[inline] + pub fn serialize(&self, bytes: &mut [u8]) { + assert!(bytes.len() == std::mem::size_of::<RawEvent>()); + + #[cfg(target_endian = "little")] + { + let raw_event_bytes: &[u8] = unsafe { + std::slice::from_raw_parts( + self as *const _ as *const u8, + std::mem::size_of::<RawEvent>(), + ) + }; + + bytes.copy_from_slice(raw_event_bytes); + } + + #[cfg(target_endian = "big")] + { + // We always emit data as little endian, which we have to do + // manually on big endian targets. + bytes[0..4].copy_from_slice(&self.event_kind.as_u32().to_le_bytes()); + bytes[4..8].copy_from_slice(&self.event_id.as_u32().to_le_bytes()); + bytes[8..12].copy_from_slice(&self.thread_id.to_le_bytes()); + bytes[12..16].copy_from_slice(&self.payload1_lower.to_le_bytes()); + bytes[16..20].copy_from_slice(&self.payload2_lower.to_le_bytes()); + bytes[20..24].copy_from_slice(&self.payloads_upper.to_le_bytes()); + } + } + + #[inline] + pub fn deserialize(bytes: &[u8]) -> RawEvent { + assert!(bytes.len() == std::mem::size_of::<RawEvent>()); + + #[cfg(target_endian = "little")] + { + let mut raw_event = RawEvent::default(); + unsafe { + let raw_event = std::slice::from_raw_parts_mut( + &mut raw_event as *mut RawEvent as *mut u8, + std::mem::size_of::<RawEvent>(), + ); + raw_event.copy_from_slice(bytes); + }; + raw_event + } + + #[cfg(target_endian = "big")] + { + RawEvent { + event_kind: StringId::new(u32::from_le_bytes(bytes[0..4].try_into().unwrap())), + event_id: EventId::from_u32(u32::from_le_bytes(bytes[4..8].try_into().unwrap())), + thread_id: u32::from_le_bytes(bytes[8..12].try_into().unwrap()), + payload1_lower: u32::from_le_bytes(bytes[12..16].try_into().unwrap()), + payload2_lower: u32::from_le_bytes(bytes[16..20].try_into().unwrap()), + payloads_upper: u32::from_le_bytes(bytes[20..24].try_into().unwrap()), + } + } + } +} + +impl Default for RawEvent { + fn default() -> Self { + RawEvent { + event_kind: StringId::INVALID, + event_id: EventId::INVALID, + thread_id: 0, + payload1_lower: 0, + payload2_lower: 0, + payloads_upper: 0, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn raw_event_has_expected_size() { + // A test case to prevent accidental regressions of RawEvent's size. + assert_eq!(std::mem::size_of::<RawEvent>(), 24); + } + + #[test] + fn is_instant() { + assert!(RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).is_instant()); + + assert!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .is_instant() + ); + + assert!(!RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 987, + 0, + MAX_INTERVAL_VALUE, + ) + .is_instant()); + } + + #[test] + fn is_integer() { + let integer = RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 0); + assert!(integer.is_integer()); + assert_eq!(integer.value(), 0); + + let integer = RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 8769); + assert!(integer.is_integer()); + assert_eq!(integer.value(), 8769); + + assert!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .is_integer() + ); + + assert!(!RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 987, + 0, + MAX_INTERVAL_VALUE, + ) + .is_integer()); + } + + #[test] + #[should_panic] + fn invalid_instant_count() { + let _ = RawEvent::new_instant( + StringId::INVALID, + EventId::INVALID, + 123, + // count too large + MAX_SINGLE_VALUE + 1, + ); + } + + #[test] + #[should_panic] + fn invalid_start_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + // start count too large + MAX_INTERVAL_VALUE + 1, + MAX_INTERVAL_VALUE + 1, + ); + } + + #[test] + #[should_panic] + fn invalid_end_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + 0, + // end count too large + MAX_INTERVAL_VALUE + 3, + ); + } + + #[test] + #[should_panic] + fn invalid_end_count2() { + let _ = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 123, 0, INTEGER_MARKER); + } + + #[test] + #[should_panic] + fn start_greater_than_end_count() { + let _ = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 123, + // start count greater than end count + 1, + 0, + ); + } + + #[test] + fn start_equal_to_end_count() { + // This is allowed, make sure we don't panic + let _ = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 123, 1, 1); + } + + #[test] + fn interval_count_decoding() { + // Check the upper limits + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + MAX_INTERVAL_VALUE, + MAX_INTERVAL_VALUE, + ); + + assert_eq!(e.start_value(), MAX_INTERVAL_VALUE); + assert_eq!(e.end_value(), MAX_INTERVAL_VALUE); + + // Check the lower limits + let e = RawEvent::new_interval(StringId::INVALID, EventId::INVALID, 1234, 0, 0); + + assert_eq!(e.start_value(), 0); + assert_eq!(e.end_value(), 0); + + // Check that end does not bleed into start + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + 0, + MAX_INTERVAL_VALUE, + ); + + assert_eq!(e.start_value(), 0); + assert_eq!(e.end_value(), MAX_INTERVAL_VALUE); + + // Test some random values + let e = RawEvent::new_interval( + StringId::INVALID, + EventId::INVALID, + 1234, + 0x1234567890, + 0x1234567890A, + ); + + assert_eq!(e.start_value(), 0x1234567890); + assert_eq!(e.end_value(), 0x1234567890A); + } + + #[test] + fn instant_count_decoding() { + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 0,).start_value(), + 0 + ); + + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, 42,).start_value(), + 42 + ); + + assert_eq!( + RawEvent::new_instant(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .start_value(), + MAX_SINGLE_VALUE + ); + } + + #[test] + fn integer_decoding() { + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 0,).start_value(), + 0 + ); + + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, 42,).start_value(), + 42 + ); + + assert_eq!( + RawEvent::new_integer(StringId::INVALID, EventId::INVALID, 987, MAX_SINGLE_VALUE,) + .start_value(), + MAX_SINGLE_VALUE + ); + } +} |