|
1 |
| -use std::mem; |
2 |
| -use std::os::unix::io::RawFd; |
3 |
| -use std::option::Option; |
4 |
| -use libc::{self, c_int, c_void}; |
5 |
| -use {Error, Result}; |
6 |
| -use errno::Errno; |
7 |
| -use ::unistd::Pid; |
8 |
| - |
9 |
| -// For some functions taking with a parameter of type CloneFlags, |
10 |
| -// only a subset of these flags have an effect. |
11 |
| -libc_bitflags!{ |
12 |
| - pub struct CloneFlags: c_int { |
13 |
| - CLONE_VM; |
14 |
| - CLONE_FS; |
15 |
| - CLONE_FILES; |
16 |
| - CLONE_SIGHAND; |
17 |
| - CLONE_PTRACE; |
18 |
| - CLONE_VFORK; |
19 |
| - CLONE_PARENT; |
20 |
| - CLONE_THREAD; |
21 |
| - CLONE_NEWNS; |
22 |
| - CLONE_SYSVSEM; |
23 |
| - CLONE_SETTLS; |
24 |
| - CLONE_PARENT_SETTID; |
25 |
| - CLONE_CHILD_CLEARTID; |
26 |
| - CLONE_DETACHED; |
27 |
| - CLONE_UNTRACED; |
28 |
| - CLONE_CHILD_SETTID; |
29 |
| - CLONE_NEWCGROUP; |
30 |
| - CLONE_NEWUTS; |
31 |
| - CLONE_NEWIPC; |
32 |
| - CLONE_NEWUSER; |
33 |
| - CLONE_NEWPID; |
34 |
| - CLONE_NEWNET; |
35 |
| - CLONE_IO; |
| 1 | +use libc; |
| 2 | +use {Errno, Result}; |
| 3 | + |
| 4 | +#[cfg(any(target_os = "android", target_os = "linux"))] |
| 5 | +pub use self::sched_linux_like::*; |
| 6 | + |
| 7 | +#[cfg(any(target_os = "android", target_os = "linux"))] |
| 8 | +mod sched_linux_like { |
| 9 | + use errno::Errno; |
| 10 | + use libc::{self, c_int, c_void}; |
| 11 | + use std::mem; |
| 12 | + use std::option::Option; |
| 13 | + use std::os::unix::io::RawFd; |
| 14 | + use unistd::Pid; |
| 15 | + use {Error, Result}; |
| 16 | + |
| 17 | + // For some functions taking with a parameter of type CloneFlags, |
| 18 | + // only a subset of these flags have an effect. |
| 19 | + libc_bitflags! { |
| 20 | + pub struct CloneFlags: c_int { |
| 21 | + CLONE_VM; |
| 22 | + CLONE_FS; |
| 23 | + CLONE_FILES; |
| 24 | + CLONE_SIGHAND; |
| 25 | + CLONE_PTRACE; |
| 26 | + CLONE_VFORK; |
| 27 | + CLONE_PARENT; |
| 28 | + CLONE_THREAD; |
| 29 | + CLONE_NEWNS; |
| 30 | + CLONE_SYSVSEM; |
| 31 | + CLONE_SETTLS; |
| 32 | + CLONE_PARENT_SETTID; |
| 33 | + CLONE_CHILD_CLEARTID; |
| 34 | + CLONE_DETACHED; |
| 35 | + CLONE_UNTRACED; |
| 36 | + CLONE_CHILD_SETTID; |
| 37 | + CLONE_NEWCGROUP; |
| 38 | + CLONE_NEWUTS; |
| 39 | + CLONE_NEWIPC; |
| 40 | + CLONE_NEWUSER; |
| 41 | + CLONE_NEWPID; |
| 42 | + CLONE_NEWNET; |
| 43 | + CLONE_IO; |
| 44 | + } |
36 | 45 | }
|
37 |
| -} |
38 | 46 |
|
39 |
| -pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>; |
40 |
| - |
41 |
| -#[repr(C)] |
42 |
| -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
43 |
| -pub struct CpuSet { |
44 |
| - cpu_set: libc::cpu_set_t, |
45 |
| -} |
| 47 | + pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>; |
46 | 48 |
|
47 |
| -impl CpuSet { |
48 |
| - pub fn new() -> CpuSet { |
49 |
| - CpuSet { cpu_set: unsafe { mem::zeroed() } } |
| 49 | + #[repr(C)] |
| 50 | + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
| 51 | + pub struct CpuSet { |
| 52 | + cpu_set: libc::cpu_set_t, |
50 | 53 | }
|
51 | 54 |
|
52 |
| - pub fn is_set(&self, field: usize) -> Result<bool> { |
53 |
| - if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
54 |
| - Err(Error::Sys(Errno::EINVAL)) |
55 |
| - } else { |
56 |
| - Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) }) |
| 55 | + impl CpuSet { |
| 56 | + pub fn new() -> CpuSet { |
| 57 | + CpuSet { |
| 58 | + cpu_set: unsafe { mem::zeroed() }, |
| 59 | + } |
57 | 60 | }
|
58 |
| - } |
59 | 61 |
|
60 |
| - pub fn set(&mut self, field: usize) -> Result<()> { |
61 |
| - if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
62 |
| - Err(Error::Sys(Errno::EINVAL)) |
63 |
| - } else { |
64 |
| - Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) }) |
| 62 | + pub fn is_set(&self, field: usize) -> Result<bool> { |
| 63 | + if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
| 64 | + Err(Error::Sys(Errno::EINVAL)) |
| 65 | + } else { |
| 66 | + Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) }) |
| 67 | + } |
65 | 68 | }
|
66 |
| - } |
67 | 69 |
|
68 |
| - pub fn unset(&mut self, field: usize) -> Result<()> { |
69 |
| - if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
70 |
| - Err(Error::Sys(Errno::EINVAL)) |
71 |
| - } else { |
72 |
| - Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) }) |
| 70 | + pub fn set(&mut self, field: usize) -> Result<()> { |
| 71 | + if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
| 72 | + Err(Error::Sys(Errno::EINVAL)) |
| 73 | + } else { |
| 74 | + Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) }) |
| 75 | + } |
73 | 76 | }
|
74 |
| - } |
75 |
| -} |
76 | 77 |
|
77 |
| -pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> { |
78 |
| - let res = unsafe { |
79 |
| - libc::sched_setaffinity(pid.into(), |
80 |
| - mem::size_of::<CpuSet>() as libc::size_t, |
81 |
| - &cpuset.cpu_set) |
82 |
| - }; |
| 78 | + pub fn unset(&mut self, field: usize) -> Result<()> { |
| 79 | + if field >= 8 * mem::size_of::<libc::cpu_set_t>() { |
| 80 | + Err(Error::Sys(Errno::EINVAL)) |
| 81 | + } else { |
| 82 | + Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) }) |
| 83 | + } |
| 84 | + } |
| 85 | + } |
83 | 86 |
|
84 |
| - Errno::result(res).map(drop) |
85 |
| -} |
| 87 | + pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> { |
| 88 | + let res = unsafe { |
| 89 | + libc::sched_setaffinity( |
| 90 | + pid.into(), |
| 91 | + mem::size_of::<CpuSet>() as libc::size_t, |
| 92 | + &cpuset.cpu_set, |
| 93 | + ) |
| 94 | + }; |
86 | 95 |
|
87 |
| -/// Explicitly yield the processor to other threads. |
88 |
| -/// |
89 |
| -/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html) |
90 |
| -pub fn sched_yield() -> Result<()> { |
91 |
| - let res = unsafe { |
92 |
| - libc::sched_yield() |
93 |
| - }; |
| 96 | + Errno::result(res).map(drop) |
| 97 | + } |
94 | 98 |
|
95 |
| - Errno::result(res).map(drop) |
96 |
| -} |
| 99 | + pub fn clone( |
| 100 | + mut cb: CloneCb, |
| 101 | + stack: &mut [u8], |
| 102 | + flags: CloneFlags, |
| 103 | + signal: Option<c_int>, |
| 104 | + ) -> Result<Pid> { |
| 105 | + extern "C" fn callback(data: *mut CloneCb) -> c_int { |
| 106 | + let cb: &mut CloneCb = unsafe { &mut *data }; |
| 107 | + (*cb)() as c_int |
| 108 | + } |
97 | 109 |
|
98 |
| -pub fn clone(mut cb: CloneCb, |
99 |
| - stack: &mut [u8], |
100 |
| - flags: CloneFlags, |
101 |
| - signal: Option<c_int>) |
102 |
| - -> Result<Pid> { |
103 |
| - extern "C" fn callback(data: *mut CloneCb) -> c_int { |
104 |
| - let cb: &mut CloneCb = unsafe { &mut *data }; |
105 |
| - (*cb)() as c_int |
| 110 | + let res = unsafe { |
| 111 | + let combined = flags.bits() | signal.unwrap_or(0); |
| 112 | + let ptr = stack.as_mut_ptr().offset(stack.len() as isize); |
| 113 | + let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1); |
| 114 | + libc::clone( |
| 115 | + mem::transmute( |
| 116 | + callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32, |
| 117 | + ), |
| 118 | + ptr_aligned as *mut c_void, |
| 119 | + combined, |
| 120 | + &mut cb as *mut _ as *mut c_void, |
| 121 | + ) |
| 122 | + }; |
| 123 | + |
| 124 | + Errno::result(res).map(Pid::from_raw) |
106 | 125 | }
|
107 | 126 |
|
108 |
| - let res = unsafe { |
109 |
| - let combined = flags.bits() | signal.unwrap_or(0); |
110 |
| - let ptr = stack.as_mut_ptr().offset(stack.len() as isize); |
111 |
| - let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1); |
112 |
| - libc::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32), |
113 |
| - ptr_aligned as *mut c_void, |
114 |
| - combined, |
115 |
| - &mut cb as *mut _ as *mut c_void) |
116 |
| - }; |
117 |
| - |
118 |
| - Errno::result(res).map(Pid::from_raw) |
119 |
| -} |
| 127 | + pub fn unshare(flags: CloneFlags) -> Result<()> { |
| 128 | + let res = unsafe { libc::unshare(flags.bits()) }; |
| 129 | + |
| 130 | + Errno::result(res).map(drop) |
| 131 | + } |
120 | 132 |
|
121 |
| -pub fn unshare(flags: CloneFlags) -> Result<()> { |
122 |
| - let res = unsafe { libc::unshare(flags.bits()) }; |
| 133 | + pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { |
| 134 | + let res = unsafe { libc::setns(fd, nstype.bits()) }; |
123 | 135 |
|
124 |
| - Errno::result(res).map(drop) |
| 136 | + Errno::result(res).map(drop) |
| 137 | + } |
125 | 138 | }
|
126 | 139 |
|
127 |
| -pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { |
128 |
| - let res = unsafe { libc::setns(fd, nstype.bits()) }; |
| 140 | +/// Explicitly yield the processor to other threads. |
| 141 | +/// |
| 142 | +/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html) |
| 143 | +pub fn sched_yield() -> Result<()> { |
| 144 | + let res = unsafe { libc::sched_yield() }; |
129 | 145 |
|
130 | 146 | Errno::result(res).map(drop)
|
131 | 147 | }
|
0 commit comments