diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/num_threads/src | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/num_threads/src')
-rw-r--r-- | rust/vendor/num_threads/src/apple.rs | 45 | ||||
-rw-r--r-- | rust/vendor/num_threads/src/freebsd.rs | 36 | ||||
-rw-r--r-- | rust/vendor/num_threads/src/imp.rs | 7 | ||||
-rw-r--r-- | rust/vendor/num_threads/src/lib.rs | 64 | ||||
-rw-r--r-- | rust/vendor/num_threads/src/linux.rs | 14 |
5 files changed, 166 insertions, 0 deletions
diff --git a/rust/vendor/num_threads/src/apple.rs b/rust/vendor/num_threads/src/apple.rs new file mode 100644 index 0000000..8d71b54 --- /dev/null +++ b/rust/vendor/num_threads/src/apple.rs @@ -0,0 +1,45 @@ +extern crate libc; + +use std::num::NonZeroUsize; + +use self::libc::{kern_return_t, mach_msg_type_number_t, mach_port_t, thread_t}; + +// This constant is from +// /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/ +// usr/include/mach/machine/thread_state.h. +// +// It has not been updated since Apple devices started to support 64-bit ARM (iOS), so it +// should be very stable. +const THREAD_STATE_MAX: i32 = 1296; +#[allow(non_camel_case_types)] +// https://github.com/apple/darwin-xnu/blob/a1babec6b135d1f35b2590a1990af3c5c5393479/osfmk/mach/mach_types.defs#L155 +type task_inspect_t = mach_port_t; +#[allow(non_camel_case_types)] +// https://github.com/apple/darwin-xnu/blob/a1babec6b135d1f35b2590a1990af3c5c5393479/osfmk/mach/mach_types.defs#L238 +type thread_array_t = [thread_t; THREAD_STATE_MAX as usize]; + +extern "C" { + // https://developer.apple.com/documentation/kernel/1537751-task_threads/ + fn task_threads( + target_task: task_inspect_t, + act_list: *mut thread_array_t, + act_listCnt: *mut mach_msg_type_number_t, + ) -> kern_return_t; +} + +pub(crate) fn num_threads() -> Option<NonZeroUsize> { + // http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_threads.html + let mut thread_state = [0u32; THREAD_STATE_MAX as usize]; + let mut thread_count = 0; + + // Safety: `mach_task_self` always returns a valid value, `thread_state` is large enough, and + // both it and `thread_count` are writable. + let result = + unsafe { task_threads(libc::mach_task_self(), &mut thread_state, &mut thread_count) }; + + if result == libc::KERN_SUCCESS { + NonZeroUsize::new(thread_count as usize) + } else { + None + } +} diff --git a/rust/vendor/num_threads/src/freebsd.rs b/rust/vendor/num_threads/src/freebsd.rs new file mode 100644 index 0000000..1c3cbc8 --- /dev/null +++ b/rust/vendor/num_threads/src/freebsd.rs @@ -0,0 +1,36 @@ +extern crate libc; + +use std::num::NonZeroUsize; +use std::{mem, ptr}; + +pub(crate) fn num_threads() -> Option<NonZeroUsize> { + // Safety: `sysctl` and `getpid` are both thread-safe. + // `kip` is only accessed if sysctl() succeeds and agrees with the expected size, + // and the data only trusted if both its embedded size and pid match expectations + unsafe { + let pid = libc::getpid(); + let mib: [libc::c_int; 4] = [libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_PID, pid]; + let mut kip: libc::kinfo_proc = mem::zeroed(); + let expected_kip_len = mem::size_of_val(&kip); + let mut kip_len = expected_kip_len; + + let ret = libc::sysctl( + mib.as_ptr(), + mib.len() as u32, + &mut kip as *mut _ as *mut libc::c_void, + &mut kip_len, + ptr::null(), + 0, + ); + + if ret == 0 + && kip_len == expected_kip_len + && kip.ki_structsize == expected_kip_len as i32 + && kip.ki_pid == pid + { + NonZeroUsize::new(kip.ki_numthreads as usize) + } else { + None + } + } +} diff --git a/rust/vendor/num_threads/src/imp.rs b/rust/vendor/num_threads/src/imp.rs new file mode 100644 index 0000000..b12465d --- /dev/null +++ b/rust/vendor/num_threads/src/imp.rs @@ -0,0 +1,7 @@ +//! Fallback if no OS matches. + +use std::num::NonZeroUsize; + +pub(crate) fn num_threads() -> Option<NonZeroUsize> { + None +} diff --git a/rust/vendor/num_threads/src/lib.rs b/rust/vendor/num_threads/src/lib.rs new file mode 100644 index 0000000..c213802 --- /dev/null +++ b/rust/vendor/num_threads/src/lib.rs @@ -0,0 +1,64 @@ +//! Minimum supported Rust version: 1.28 + +use std::num::NonZeroUsize; + +#[cfg_attr(any(target_os = "linux", target_os = "android"), path = "linux.rs")] +#[cfg_attr(target_os = "freebsd", path = "freebsd.rs")] +#[cfg_attr(any(target_os = "macos", target_os = "ios"), path = "apple.rs")] +mod imp; + +/// Obtain the number of threads currently part of the active process. Returns `None` if the number +/// of threads cannot be determined. +pub fn num_threads() -> Option<NonZeroUsize> { + imp::num_threads() +} + +/// Determine if the current process is single-threaded. Returns `None` if the number of threads +/// cannot be determined. +pub fn is_single_threaded() -> Option<bool> { + num_threads().map(|n| n.get() == 1) +} + +#[cfg(test)] +mod test { + use std::num::NonZeroUsize; + + // Run each expression in its own thread. + macro_rules! threaded { + ($first:expr;) => { + $first; + }; + ($first:expr; $($rest:expr;)*) => { + $first; + ::std::thread::spawn(|| { + threaded!($($rest;)*); + }) + .join() + .unwrap(); + }; + } + + #[test] + fn num_threads() { + threaded! { + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(1)); + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(2)); + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(3)); + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(4)); + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(5)); + assert_eq!(super::num_threads().map(NonZeroUsize::get), Some(6)); + } + } + + #[test] + fn is_single_threaded() { + threaded! { + assert_eq!(super::is_single_threaded(), Some(true)); + assert_eq!(super::is_single_threaded(), Some(false)); + assert_eq!(super::is_single_threaded(), Some(false)); + assert_eq!(super::is_single_threaded(), Some(false)); + assert_eq!(super::is_single_threaded(), Some(false)); + assert_eq!(super::is_single_threaded(), Some(false)); + } + } +} diff --git a/rust/vendor/num_threads/src/linux.rs b/rust/vendor/num_threads/src/linux.rs new file mode 100644 index 0000000..641b6b1 --- /dev/null +++ b/rust/vendor/num_threads/src/linux.rs @@ -0,0 +1,14 @@ +use std::fs; +use std::num::NonZeroUsize; + +pub(crate) fn num_threads() -> Option<NonZeroUsize> { + fs::read_to_string("/proc/self/stat") + .ok() + .as_ref() + // Skip past the pid and (process name) fields + .and_then(|stat| stat.rsplit(')').next()) + // 20th field, less the two we skipped + .and_then(|rstat| rstat.split_whitespace().nth(17)) + .and_then(|num_threads| num_threads.parse::<usize>().ok()) + .and_then(NonZeroUsize::new) +} |