aocl_utils/threads.rs
1//! Thread-pinning helpers from AOCL-Utils.
2//!
3//! These are very thin wrappers around the AOCL routines that take a
4//! list of OS-level thread handles (`pthread_t` on Unix, `HANDLE` on
5//! Windows) and pin them to physical or logical cores. Most callers
6//! collect `pthread_t` / `HANDLE` values from their thread library
7//! (`std::thread::current().handle()`-style accessors via `os`-specific
8//! crates) before invoking these.
9//!
10//! The functions are `unsafe` because passing a thread handle that no
11//! longer refers to a live thread is undefined behavior on the AOCL
12//! side.
13
14use aocl_utils_sys as sys;
15
16/// OS-native thread handle.
17pub type ThreadHandle = sys::pthread_t;
18
19/// Pinning strategy for a list of thread handles.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21pub enum PinStrategy {
22 /// Pin each thread to a unique physical core (one thread per core,
23 /// preferring physical core 0, 1, 2, …).
24 Core,
25 /// Pin each thread to a unique logical processor (SMT thread).
26 Logical,
27 /// Spread threads across cores to maximize per-thread cache, mapping
28 /// each thread to a different L3 / NUMA region when possible.
29 Spread,
30}
31
32/// Pin the given thread handles using the chosen strategy.
33///
34/// # Safety
35///
36/// Each entry of `threads` must be a valid OS-level handle to a still-live
37/// thread. Passing a stale handle (e.g. for a thread that has exited or
38/// been detached) is undefined behavior. The slice's length must fit in
39/// a C `size_t`.
40pub unsafe fn pin_threads(strategy: PinStrategy, threads: &mut [ThreadHandle]) {
41 let n = threads.len();
42 let p = threads.as_mut_ptr();
43 match strategy {
44 PinStrategy::Core => unsafe { sys::au_pin_threads_core(p, n) },
45 PinStrategy::Logical => unsafe { sys::au_pin_threads_logical(p, n) },
46 PinStrategy::Spread => unsafe { sys::au_pin_threads_spread(p, n) },
47 }
48}
49
50/// Pin threads with a custom mapping: `affinity_vector[i]` is the logical
51/// processor index thread `i` should bind to.
52///
53/// # Safety
54///
55/// Same as [`pin_threads`]; in addition, the affinity values must
56/// reference logical processors that exist on the host.
57pub unsafe fn pin_threads_custom(threads: &mut [ThreadHandle], affinity_vector: &[i32]) {
58 let n = threads.len();
59 if n == 0 || affinity_vector.is_empty() {
60 return;
61 }
62 unsafe {
63 sys::au_pin_threads_custom(
64 threads.as_mut_ptr(),
65 n,
66 affinity_vector.as_ptr() as *mut std::os::raw::c_int,
67 affinity_vector.len(),
68 );
69 }
70}