From dfd72c97da63e0da59be49e220768881e1037716 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 --- Cargo.toml | 2 +- src/sched.rs | 119 ++++++++++++++++++++++++++++----------------------- 2 files changed, 66 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 298c16ebb8..802bd32971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.102", features = [ "extra_traits" ] } +libc = { git = "https://github.com/rust-lang/libc", rev = "971fde3d7", 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.