diff --git a/CHANGELOG.md b/CHANGELOG.md index 08939e0064..04e9322f64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#405](https://github.com/nix-rust/nix/pull/405)) - Added `F_FULLFSYNC` to `FcntlArg` in `::nix::fcntl` for _apple_ targets. ([#407](https://github.com/nix-rust/nix/pull/407)) +- Added `CpuSet::unset` in `::nix::sched`. + ([#402](https://github.com/nix-rust/nix/pull/402)) ### Changed - Replaced the reexported integer constants for signals by the enumeration @@ -28,10 +30,16 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#362](https://github.com/nix-rust/nix/pull/362)) - Renamed `EventFdFlag` to `EfdFlags` in `::nix::sys::eventfd`. ([#383](https://github.com/nix-rust/nix/pull/383)) +- Changed the result types of `CpuSet::is_set` and `CpuSet::set` in + `::nix::sched` to `Result` and `Result<()>`, respectively. They now + return `EINVAL`, if an invalid argument for the `field` parameter is passed. + ([#402](https://github.com/nix-rust/nix/pull/402)) ### Removed - Type alias `SigNum` from `::nix::sys::signal`. ([#362](https://github.com/nix-rust/nix/pull/362)) +- Type alias `CpuMask` from `::nix::shed`. + ([#402](https://github.com/nix-rust/nix/pull/402)) ### Fixed - Fixed the build problem for NetBSD (Note, that we currently do not support diff --git a/src/sched.rs b/src/sched.rs index 934ce13ff9..91a7c42a9a 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -1,204 +1,110 @@ use std::mem; use std::os::unix::io::RawFd; use std::option::Option; -use libc::{self, c_int, c_void, c_ulong, pid_t}; -use {Errno, Result}; +use libc::{self, c_int, c_void, pid_t}; +use {Errno, Error, Result}; // For some functions taking with a parameter of type CloneFlags, // only a subset of these flags have an effect. -bitflags!{ - flags CloneFlags: c_int { - const CLONE_VM = libc::CLONE_VM, - const CLONE_FS = libc::CLONE_FS, - const CLONE_FILES = libc::CLONE_FILES, - const CLONE_SIGHAND = libc::CLONE_SIGHAND, - const CLONE_PTRACE = libc::CLONE_PTRACE, - const CLONE_VFORK = libc::CLONE_VFORK, - const CLONE_PARENT = libc::CLONE_PARENT, - const CLONE_THREAD = libc::CLONE_THREAD, - const CLONE_NEWNS = libc::CLONE_NEWNS, - const CLONE_SYSVSEM = libc::CLONE_SYSVSEM, - const CLONE_SETTLS = libc::CLONE_SETTLS, - const CLONE_PARENT_SETTID = libc::CLONE_PARENT_SETTID, - const CLONE_CHILD_CLEARTID = libc::CLONE_CHILD_CLEARTID, - const CLONE_DETACHED = libc::CLONE_DETACHED, - const CLONE_UNTRACED = libc::CLONE_UNTRACED, - const CLONE_CHILD_SETTID = libc::CLONE_CHILD_SETTID, - // TODO: Once, we use a version containing - // https://github.com/rust-lang-nursery/libc/pull/147 - // get rid of the casts. - const CLONE_NEWUTS = libc::CLONE_NEWUTS as c_int, - const CLONE_NEWIPC = libc::CLONE_NEWIPC as c_int, - const CLONE_NEWUSER = libc::CLONE_NEWUSER as c_int, - const CLONE_NEWPID = libc::CLONE_NEWPID as c_int, - const CLONE_NEWNET = libc::CLONE_NEWNET as c_int, - const CLONE_IO = libc::CLONE_IO as c_int, - } -} - -// Support a maximum CPU set of 1024 nodes -#[cfg(all(target_arch = "x86_64", target_os = "linux"))] -mod cpuset_attribs { - use super::CpuMask; - pub const CPU_SETSIZE: usize = 1024; - pub const CPU_MASK_BITS: usize = 64; - - #[inline] - pub fn set_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur | (1u64 << bit) - } - - #[inline] - pub fn clear_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur & !(1u64 << bit) - } -} - -#[cfg(all(target_arch = "x86", target_os = "linux"))] -mod cpuset_attribs { - use super::CpuMask; - pub const CPU_SETSIZE: usize = 1024; - pub const CPU_MASK_BITS: usize = 32; - - #[inline] - pub fn set_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur | (1u32 << bit) - } - - #[inline] - pub fn clear_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur & !(1u32 << bit) - } -} - -#[cfg(all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")))] -mod cpuset_attribs { - use super::CpuMask; - pub const CPU_SETSIZE: usize = 1024; - pub const CPU_MASK_BITS: usize = 64; - - #[inline] - pub fn set_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur | (1u64 << bit) - } - - #[inline] - pub fn clear_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur & !(1u64 << bit) - } -} - -#[cfg(all(any(target_arch = "arm", target_arch = "mips"), target_os = "android"))] -mod cpuset_attribs { - use super::CpuMask; - // bionic only supports up to 32 independent CPUs, instead of 1024. - pub const CPU_SETSIZE: usize = 32; - pub const CPU_MASK_BITS: usize = 32; - - #[inline] - pub fn set_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur | (1u32 << bit) - } - - #[inline] - pub fn clear_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur & !(1u32 << bit) - } -} - -#[cfg(all(any(target_arch = "arm", target_arch = "mips"), target_os = "linux"))] -mod cpuset_attribs { - use super::CpuMask; - pub const CPU_SETSIZE: usize = 1024; - pub const CPU_MASK_BITS: usize = 32; - - #[inline] - pub fn set_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur | (1u32 << bit) - } - - #[inline] - pub fn clear_cpu_mask_flag(cur: CpuMask, bit: usize) -> CpuMask { - cur & !(1u32 << bit) +libc_bitflags!{ + flags CloneFlags: libc::c_int { + CLONE_VM, + CLONE_FS, + CLONE_FILES, + CLONE_SIGHAND, + CLONE_PTRACE, + CLONE_VFORK, + CLONE_PARENT, + CLONE_THREAD, + CLONE_NEWNS, + CLONE_SYSVSEM, + CLONE_SETTLS, + CLONE_PARENT_SETTID, + CLONE_CHILD_CLEARTID, + CLONE_DETACHED, + CLONE_UNTRACED, + CLONE_CHILD_SETTID, + CLONE_NEWUTS, + CLONE_NEWIPC, + CLONE_NEWUSER, + CLONE_NEWPID, + CLONE_NEWNET, + CLONE_IO, } } pub type CloneCb<'a> = Box isize + 'a>; -// A single CPU mask word -pub type CpuMask = c_ulong; - -// Structure representing the CPU set to apply #[repr(C)] #[derive(Clone, Copy)] pub struct CpuSet { - cpu_mask: [CpuMask; cpuset_attribs::CPU_SETSIZE/cpuset_attribs::CPU_MASK_BITS] + cpu_set: libc::cpu_set_t, } impl CpuSet { pub fn new() -> CpuSet { - CpuSet { - cpu_mask: unsafe { mem::zeroed() } - } + CpuSet { cpu_set: unsafe { mem::zeroed() } } } - pub fn set(&mut self, field: usize) { - let word = field / cpuset_attribs::CPU_MASK_BITS; - let bit = field % cpuset_attribs::CPU_MASK_BITS; - - self.cpu_mask[word] = cpuset_attribs::set_cpu_mask_flag(self.cpu_mask[word], bit); + pub fn is_set(&self, field: usize) -> Result { + if field >= 8 * mem::size_of::() { + Err(Error::Sys(Errno::EINVAL)) + } else { + Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) }) + } } - pub fn unset(&mut self, field: usize) { - let word = field / cpuset_attribs::CPU_MASK_BITS; - let bit = field % cpuset_attribs::CPU_MASK_BITS; + pub fn set(&mut self, field: usize) -> Result<()> { + if field >= 8 * mem::size_of::() { + Err(Error::Sys(Errno::EINVAL)) + } else { + Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) }) + } + } - self.cpu_mask[word] = cpuset_attribs::clear_cpu_mask_flag(self.cpu_mask[word], bit); + pub fn unset(&mut self, field: usize) -> Result<()> { + if field >= 8 * mem::size_of::() { + Err(Error::Sys(Errno::EINVAL)) + } else { + Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) }) + } } } mod ffi { - use libc::{c_void, c_int, pid_t, size_t}; - use super::CpuSet; + use libc::{c_void, c_int}; - pub type CloneCb = extern "C" fn (data: *const super::CloneCb) -> c_int; + pub type CloneCb = extern "C" fn(data: *const super::CloneCb) -> c_int; // We cannot give a proper #[repr(C)] to super::CloneCb #[allow(improper_ctypes)] - extern { + extern "C" { // create a child process // doc: http://man7.org/linux/man-pages/man2/clone.2.html - pub fn clone( - cb: *const CloneCb, - child_stack: *mut c_void, - flags: c_int, - arg: *mut super::CloneCb, - ...) -> c_int; - - // disassociate parts of the process execution context - // doc: http://man7.org/linux/man-pages/man2/unshare.2.html - pub fn unshare(flags: c_int) -> c_int; - - // reassociate thread with a namespace - // doc: http://man7.org/linux/man-pages/man2/setns.2.html - pub fn setns(fd: c_int, nstype: c_int) -> c_int; - - // Set the current CPU set that a task is allowed to run on - pub fn sched_setaffinity(__pid: pid_t, __cpusetsize: size_t, __cpuset: *const CpuSet) -> c_int; + pub fn clone(cb: *const CloneCb, + child_stack: *mut c_void, + flags: c_int, + arg: *mut super::CloneCb, + ...) + -> c_int; } } pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> Result<()> { - use libc::{pid_t, size_t}; - let res = unsafe { - ffi::sched_setaffinity(pid as pid_t, mem::size_of::() as size_t, mem::transmute(cpuset)) + libc::sched_setaffinity(pid as libc::pid_t, + mem::size_of::() as libc::size_t, + mem::transmute(cpuset)) }; Errno::result(res).map(drop) } -pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags, signal: Option) -> Result { +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 @@ -217,13 +123,13 @@ pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags, signal: Optio } pub fn unshare(flags: CloneFlags) -> Result<()> { - let res = unsafe { ffi::unshare(flags.bits()) }; + let res = unsafe { libc::unshare(flags.bits()) }; Errno::result(res).map(drop) } pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { - let res = unsafe { ffi::setns(fd, nstype.bits()) }; + let res = unsafe { libc::setns(fd, nstype.bits()) }; Errno::result(res).map(drop) }