summaryrefslogtreecommitdiff
path: root/src/sched.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sched.rs')
-rw-r--r--src/sched.rs226
1 files changed, 66 insertions, 160 deletions
diff --git a/src/sched.rs b/src/sched.rs
index 934ce13f..91a7c42a 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<FnMut() -> 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<bool> {
+ if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
+ 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::<libc::cpu_set_t>() {
+ 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::<libc::cpu_set_t>() {
+ 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::<CpuSet>() as size_t, mem::transmute(cpuset))
+ libc::sched_setaffinity(pid as libc::pid_t,
+ mem::size_of::<CpuSet>() 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<c_int>) -> Result<pid_t> {
+pub fn clone(mut cb: CloneCb,
+ stack: &mut [u8],
+ flags: CloneFlags,
+ signal: Option<c_int>)
+ -> Result<pid_t> {
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)
}