Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable sched_get/setaffinity on DragonflyBSD
Browse files Browse the repository at this point in the history
rtzoeller committed Sep 28, 2021
1 parent 9a2f86f commit 63a5c86
Showing 4 changed files with 69 additions and 55 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"

119 changes: 65 additions & 54 deletions src/sched.rs
Original file line number Diff line number Diff line change
@@ -86,6 +86,71 @@ mod sched_linux_like {
/// Type for the function executed by [`clone`].
pub type CloneCb<'a> = Box<dyn FnMut() -> 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<c_int>,
) -> Result<Pid> {
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<dyn FnMut() -> 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<c_int>,
) -> Result<Pid> {
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<dyn FnMut() -> 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.
1 change: 1 addition & 0 deletions test/test.rs
Original file line number Diff line number Diff line change
@@ -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",

0 comments on commit 63a5c86

Please sign in to comment.