From 08f7d9e24f2c91636e71ea996cc08a6453501077 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Sun, 14 Nov 2021 23:14:09 -0500 Subject: [PATCH] Implement Linux, FreeBSD --- .github/workflows/build.yaml | 6 +++--- Cargo.toml | 4 +++- src/freebsd.rs | 13 +++++++++++++ src/imp.rs | 7 +++++++ src/lib.rs | 20 +++++++++++++++++++- src/linux.rs | 10 ++++++++++ 6 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 src/freebsd.rs create mode 100644 src/imp.rs create mode 100644 src/linux.rs diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 40196ed..2813b39 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -25,7 +25,7 @@ on: - .gitignore jobs: - check-other-targets: + check: name: Type checking (${{ matrix.target.name }}) runs-on: ubuntu-20.04 if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork) || github.event_name == 'push' }} @@ -49,7 +49,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.36 + toolchain: 1.28 target: ${{ matrix.target.triple }} override: true @@ -58,7 +58,7 @@ jobs: with: key: ${{ matrix.target.triple }} - - name: Check feature powerset + - name: Type checking uses: actions-rs/cargo@v1 with: command: check diff --git a/Cargo.toml b/Cargo.toml index e345c66..61f17fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ name = "num_threads" version = "0.1.0" authors = ["Jacob Pratt "] -edition = "2018" repository = "https://github.com/jhpratt/thread_count" categories = ["api-bindings", "hardware-support", "os"] license = "MIT OR Apache-2.0" @@ -14,3 +13,6 @@ all-features = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] + +[target.'cfg(target_os = "freebsd")'.dependencies] +libc = "0.2.107" diff --git a/src/freebsd.rs b/src/freebsd.rs new file mode 100644 index 0000000..3ff8f61 --- /dev/null +++ b/src/freebsd.rs @@ -0,0 +1,13 @@ +extern crate libc; + +use std::num::NonZeroUsize; + +extern "C" { + fn kinfo_getproc(pid: libc::pid_t) -> *mut libc::kinfo_proc; +} + +pub(crate) fn num_threads() -> Option { + // Safety: `kinfo_getproc` and `getpid` are both thread-safe. All invariants of `as_ref` are + // upheld. + NonZeroUsize::new(unsafe { kinfo_getproc(libc::getpid()).as_ref() }?.ki_numthreads as usize) +} diff --git a/src/imp.rs b/src/imp.rs new file mode 100644 index 0000000..b12465d --- /dev/null +++ b/src/imp.rs @@ -0,0 +1,7 @@ +//! Fallback if no OS matches. + +use std::num::NonZeroUsize; + +pub(crate) fn num_threads() -> Option { + None +} diff --git a/src/lib.rs b/src/lib.rs index e989fca..09901af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,19 @@ -//! Minimum supported Rust version: 1.36 +//! Minimum supported Rust version: 1.28 + +use std::num::NonZeroUsize; + +#[cfg_attr(target_os = "linux", path = "linux.rs")] +#[cfg_attr(target_os = "freebsd", path = "freebsd.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 { + 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 { + num_threads().map(|n| n.get() == 1) +} diff --git a/src/linux.rs b/src/linux.rs new file mode 100644 index 0000000..e110c74 --- /dev/null +++ b/src/linux.rs @@ -0,0 +1,10 @@ +use std::fs; +use std::num::NonZeroUsize; + +pub(crate) fn num_threads() -> Option { + fs::read_dir("/proc/self/task") + // If we can't read the directory, return `None`. + .ok() + // The number of files in the directory is the number of threads. + .and_then(|tasks| NonZeroUsize::new(tasks.count())) +}