summaryrefslogtreecommitdiffstats
path: root/rust/vendor/num_threads/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/num_threads/src
parentInitial commit. (diff)
downloadsuricata-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.rs45
-rw-r--r--rust/vendor/num_threads/src/freebsd.rs36
-rw-r--r--rust/vendor/num_threads/src/imp.rs7
-rw-r--r--rust/vendor/num_threads/src/lib.rs64
-rw-r--r--rust/vendor/num_threads/src/linux.rs14
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)
+}