-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rust: add support for Intel PT regions (#140)
* rust: add `__itt*` functions in generated bindings This change adds some bindgen-generated functions, and not just variables, to the generated bindings. This should resolve #139 by making the `pt_region_*` functions at least visibile in the `ittapi-sys` crate, making it possible to add higher-level Rust versions. We cannot generate bindings for all declared functions because these cause link errors: they are only present in the dynamic library (`*.so`) but not in the static library (`libittnotify.a`) that the `ittapi-sys` crate links to. So, for these dynamically-provided functions we must just retain the `*_ptr__3_0` data symbols and wait for them to be resolved to functions pointers at runtime. * rust: remove unused code * rust: document static/dynamic linking in `README.md` It is easy to forget how the `ittapi` system of static + dynamic linking works (and why!). To answer the underlying question of issues like #139, this change adds some `README.md` documentation explaining why we can't just include all function symbols in the generated bindings. * rust: add `Region` for marking Intel PT regions In #139, @codecnotsupported pointed out a need for access to `__itt_mark_pt_region_begin` and `__itt_mark_pt_region_end` for fine-grained VTune analysis using Intel PT. This change adds a high-level `Region` structure for easy access to these now-available functions. Closes #139.
- Loading branch information
Showing
15 changed files
with
168 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,5 +28,5 @@ exclude = [ | |
cc = "1.0.73" | ||
|
||
[dev-dependencies] | ||
bindgen = "0.68" | ||
bindgen = "0.69.4" | ||
diff = "0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use std::ffi::CString; | ||
|
||
/// An Intel® Processor Trace region. | ||
pub struct Region(ittapi_sys::__itt_pt_region); | ||
impl Region { | ||
/// Create a new Intel PT region. | ||
/// | ||
/// ``` | ||
/// # use ittapi::Region; | ||
/// let region = Region::new("test-region"); | ||
/// ``` | ||
/// | ||
/// # Panics | ||
/// | ||
/// Panics if the domain name contains a `0` byte. | ||
#[must_use] | ||
pub fn new(name: &str) -> Self { | ||
let c_string = | ||
CString::new(name).expect("unable to create a CString; does it contain a 0 byte?"); | ||
#[cfg(unix)] | ||
let create_fn = unsafe { ittapi_sys::__itt_pt_region_create_ptr__3_0 }; | ||
#[cfg(windows)] | ||
let create_fn = unsafe { ittapi_sys::__itt_pt_region_createA_ptr__3_0 }; | ||
let region = if let Some(create_fn) = create_fn { | ||
unsafe { create_fn(c_string.as_ptr()) } | ||
} else { | ||
// Use this value as a sentinel to indicate that the region was not created. | ||
u8::MAX | ||
}; | ||
Self(region) | ||
} | ||
|
||
/// Mark a section of code as an Intel PT region using `__itt_mark_pt_region_begin`. This can be | ||
/// used for fine-grained profiling, such as [anomaly detection] (a preview feature of VTune). | ||
/// | ||
/// [anomaly detection]: | ||
/// https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/2024-1/anomaly-detection-analysis.html | ||
/// | ||
/// ``` | ||
/// # use ittapi::Region; | ||
/// let region = Region::new("test-region"); | ||
/// // Mark a region for fine-grained measurement, such as a tight loop. | ||
/// for _ in 0..10 { | ||
/// let _marked = region.mark(); | ||
/// let _ = 2 + 2; | ||
/// // Marked region ends here, when dropped; use `end()` to end it explicitly. | ||
/// } | ||
/// ``` | ||
#[inline] | ||
#[must_use] | ||
pub fn mark(&self) -> MarkedRegion { | ||
unsafe { ittapi_sys::__itt_mark_pt_region_begin(self.0) }; | ||
MarkedRegion(self) | ||
} | ||
} | ||
|
||
/// A [`MarkedRegion`] is a Rust helper structure for ergonomically ending a marked region using | ||
/// `__itt_mark_pt_region_end`. See [`Region::mark`] for more details. | ||
pub struct MarkedRegion<'a>(&'a Region); | ||
impl<'a> MarkedRegion<'a> { | ||
/// End the marked region. | ||
#[inline] | ||
pub fn end(self) { | ||
// Do nothing; the `Drop` implementation does the work. See discussion at | ||
// https://stackoverflow.com/questions/53254645. | ||
} | ||
} | ||
impl Drop for MarkedRegion<'_> { | ||
#[inline] | ||
fn drop(&mut self) { | ||
unsafe { ittapi_sys::__itt_mark_pt_region_end(self.0 .0) }; | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
#[should_panic(expected = "unable to create a CString; does it contain a 0 byte?")] | ||
fn zero_byte() { | ||
let _region = Region::new("zero\0byte\0name"); | ||
} | ||
|
||
#[test] | ||
fn sanity() { | ||
let region = Region::new("region"); | ||
for _ in 0..10 { | ||
let _marked_region = region.mark(); | ||
// Do nothing. | ||
_marked_region.end(); | ||
} | ||
} | ||
} |