From 63a5c862797778e8f93877f0dce306a964c1e25b Mon Sep 17 00:00:00 2001 From: Ryan Zoeller Date: Wed, 22 Sep 2021 14:48:12 -0500 Subject: [PATCH] Enable sched_get/setaffinity on DragonflyBSD --- CHANGELOG.md | 2 + Cargo.toml | 2 +- src/sched.rs | 119 ++++++++++++++++++++++++++++----------------------- test/test.rs | 1 + 4 files changed, 69 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81268a0e5..44003cb989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). (#[1534](https://github.com/nix-rust/nix/pull/1534)) - Added read/write accessors for 'events' on `PollFd`. (#[1517](https://github.com/nix-rust/nix/pull/1517)) +- Added `sched_setaffinity` and `sched_getaffinity` for DragonFlyBSD. + (#[1537](https://github.com/nix-rust/nix/pull/1537)) ### Changed diff --git a/Cargo.toml b/Cargo.toml index 298c16ebb8..c4b04bbfc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.102", features = [ "extra_traits" ] } +libc = { version = "0.2.103", features = [ "extra_traits" ] } bitflags = "1.3.1" cfg-if = "1.0" diff --git a/src/sched.rs b/src/sched.rs index c2dd7b84ce..70aa1d8c49 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -86,6 +86,71 @@ mod sched_linux_like { /// Type for the function executed by [`clone`]. pub type CloneCb<'a> = Box isize + 'a>; + /// `clone` create a child process + /// ([`clone(2)`](https://man7.org/linux/man-pages/man2/clone.2.html)) + /// + /// `stack` is a reference to an array which will hold the stack of the new + /// process. Unlike when calling `clone(2)` from C, the provided stack + /// address need not be the highest address of the region. Nix will take + /// care of that requirement. The user only needs to provide a reference to + /// a normally allocated buffer. + pub fn clone( + mut cb: CloneCb, + stack: &mut [u8], + flags: CloneFlags, + signal: Option, + ) -> Result { + extern "C" fn callback(data: *mut CloneCb) -> c_int { + let cb: &mut CloneCb = unsafe { &mut *data }; + (*cb)() as c_int + } + + let res = unsafe { + let combined = flags.bits() | signal.unwrap_or(0); + let ptr = stack.as_mut_ptr().add(stack.len()); + let ptr_aligned = ptr.sub(ptr as usize % 16); + libc::clone( + mem::transmute( + callback as extern "C" fn(*mut Box isize>) -> i32, + ), + ptr_aligned as *mut c_void, + combined, + &mut cb as *mut _ as *mut c_void, + ) + }; + + Errno::result(res).map(Pid::from_raw) + } + + /// disassociate parts of the process execution context + /// + /// See also [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html) + pub fn unshare(flags: CloneFlags) -> Result<()> { + let res = unsafe { libc::unshare(flags.bits()) }; + + Errno::result(res).map(drop) + } + + /// reassociate thread with a namespace + /// + /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html) + pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { + let res = unsafe { libc::setns(fd, nstype.bits()) }; + + Errno::result(res).map(drop) + } +} + +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux"))] +pub use self::sched_affinity::*; + +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux"))] +mod sched_affinity { + use crate::errno::Errno; + use std::mem; + use crate::unistd::Pid; + use crate::Result; + /// CpuSet represent a bit-mask of CPUs. /// CpuSets are used by sched_setaffinity and /// sched_getaffinity for example. @@ -216,60 +281,6 @@ mod sched_linux_like { Errno::result(res).and(Ok(cpuset)) } - - /// `clone` create a child process - /// ([`clone(2)`](https://man7.org/linux/man-pages/man2/clone.2.html)) - /// - /// `stack` is a reference to an array which will hold the stack of the new - /// process. Unlike when calling `clone(2)` from C, the provided stack - /// address need not be the highest address of the region. Nix will take - /// care of that requirement. The user only needs to provide a reference to - /// a normally allocated buffer. - pub fn clone( - mut cb: CloneCb, - stack: &mut [u8], - flags: CloneFlags, - signal: Option, - ) -> Result { - extern "C" fn callback(data: *mut CloneCb) -> c_int { - let cb: &mut CloneCb = unsafe { &mut *data }; - (*cb)() as c_int - } - - let res = unsafe { - let combined = flags.bits() | signal.unwrap_or(0); - let ptr = stack.as_mut_ptr().add(stack.len()); - let ptr_aligned = ptr.sub(ptr as usize % 16); - libc::clone( - mem::transmute( - callback as extern "C" fn(*mut Box isize>) -> i32, - ), - ptr_aligned as *mut c_void, - combined, - &mut cb as *mut _ as *mut c_void, - ) - }; - - Errno::result(res).map(Pid::from_raw) - } - - /// disassociate parts of the process execution context - /// - /// See also [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html) - pub fn unshare(flags: CloneFlags) -> Result<()> { - let res = unsafe { libc::unshare(flags.bits()) }; - - Errno::result(res).map(drop) - } - - /// reassociate thread with a namespace - /// - /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html) - pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { - let res = unsafe { libc::setns(fd, nstype.bits()) }; - - Errno::result(res).map(drop) - } } /// Explicitly yield the processor to other threads. diff --git a/test/test.rs b/test/test.rs index b882d17485..440413c369 100644 --- a/test/test.rs +++ b/test/test.rs @@ -29,6 +29,7 @@ mod test_poll; #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] mod test_pty; #[cfg(any(target_os = "android", + target_os = "dragonfly", target_os = "linux"))] mod test_sched; #[cfg(any(target_os = "android",