Skip to content

Commit fd50bab

Browse files
committed
Remove usage of rustix in favor of libc (again)
While rustix is more efficient in certain cases as it can avoid libc calls in certain places, the resulting API isn't always nice. In particular the kqueue wrappers are unnecessarily complicated/frustrating to work with. In addition, with more and more libc related logic being moved into the standard library there's just not really a reason to keep using rustix. This commit replaces all rustix code with the equivalent libc crate code. Changelog: changed
1 parent 7685c08 commit fd50bab

File tree

8 files changed

+110
-69
lines changed

8 files changed

+110
-69
lines changed

rt/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustix::param::page_size;
1+
use crate::mem::page_size;
22
use std::env::var;
33
use std::thread::available_parallelism;
44

rt/src/mem.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::result::error_to_int;
2+
use libc::{sysconf, _SC_PAGESIZE};
23
use std::alloc::{alloc, alloc_zeroed, handle_alloc_error, Layout};
34
use std::io;
45
use std::mem::{align_of, forget, size_of};
@@ -11,6 +12,10 @@ use std::string::String as RustString;
1112
/// The alignment to use for Inko objects.
1213
const ALIGNMENT: usize = align_of::<usize>();
1314

15+
pub(crate) fn page_size() -> usize {
16+
unsafe { sysconf(_SC_PAGESIZE) as usize }
17+
}
18+
1419
pub(crate) fn allocate(layout: Layout) -> *mut u8 {
1520
unsafe {
1621
let ptr = alloc(layout);

rt/src/memory_map.rs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use rustix::mm::{
2-
mmap_anonymous, mprotect, munmap, MapFlags, MprotectFlags, ProtFlags,
1+
use libc::{
2+
c_int, mmap, mprotect, munmap, MAP_ANON, MAP_FAILED, MAP_PRIVATE,
3+
PROT_NONE, PROT_READ, PROT_WRITE,
34
};
45
use std::io::{Error, Result as IoResult};
56
use std::ptr::null_mut;
67

7-
fn mmap_options(_stack: bool) -> MapFlags {
8-
let base = MapFlags::PRIVATE;
8+
fn mmap_options(_stack: bool) -> c_int {
9+
let base = MAP_PRIVATE | MAP_ANON;
910

1011
// For FreeBSD we _shouldn't_ use MAP_STACK, as this inserts an implicit
1112
// guard page at the start of the returned pointer, and this could mess up
@@ -16,7 +17,7 @@ fn mmap_options(_stack: bool) -> MapFlags {
1617
// OpenBSD doesn't have this behaviour, and on Linux MAP_STACK is a no-op.
1718
#[cfg(any(target_os = "linux", target_os = "openbsd"))]
1819
if _stack {
19-
return base | MapFlags::STACK;
20+
return base | libc::MAP_STACK;
2021
}
2122

2223
base
@@ -38,22 +39,13 @@ impl MemoryMap {
3839
// more and manually align the resulting pointer.
3940
let alloc_size = size * 2;
4041
let opts = mmap_options(true);
41-
let res = unsafe {
42-
mmap_anonymous(
43-
null_mut(),
44-
alloc_size,
45-
ProtFlags::READ | ProtFlags::WRITE,
46-
opts,
47-
)
42+
let ptr = unsafe {
43+
mmap(null_mut(), alloc_size, PROT_READ | PROT_WRITE, opts, -1, 0)
4844
};
4945

50-
let ptr = match res {
51-
Ok(ptr) => ptr as *mut u8,
52-
Err(e) => panic!(
53-
"mmap(2) failed: {}",
54-
Error::from_raw_os_error(e.raw_os_error())
55-
),
56-
};
46+
if ptr == MAP_FAILED {
47+
panic!("mmap(2) failed: {}", Error::last_os_error());
48+
}
5749

5850
let start = ((ptr as usize + (size - 1)) & !(size - 1)) as *mut u8;
5951
let end = start as usize + size;
@@ -82,13 +74,13 @@ impl MemoryMap {
8274
start: usize,
8375
size: usize,
8476
) -> IoResult<()> {
85-
let res = unsafe {
86-
mprotect(self.ptr.add(start) as _, size, MprotectFlags::empty())
87-
};
77+
let res =
78+
unsafe { mprotect(self.ptr.add(start) as _, size, PROT_NONE) };
8879

89-
match res {
90-
Ok(_) => Ok(()),
91-
Err(e) => Err(Error::from_raw_os_error(e.raw_os_error())),
80+
if res == 0 {
81+
Ok(())
82+
} else {
83+
Err(Error::last_os_error())
9284
}
9385
}
9486
}
@@ -104,7 +96,7 @@ impl Drop for MemoryMap {
10496
#[cfg(test)]
10597
mod tests {
10698
use super::*;
107-
use rustix::param::page_size;
99+
use crate::mem::page_size;
108100

109101
#[test]
110102
fn test_new() {

rt/src/network_poller.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Polling of non-blocking sockets using the system's polling mechanism.
22
use crate::process::{ProcessPointer, RescheduleRights};
33
use crate::state::RcState;
4-
use rustix::fd::AsFd;
4+
use std::os::fd::{AsFd, AsRawFd};
55

66
#[cfg(target_os = "linux")]
77
mod epoll;
@@ -47,7 +47,7 @@ impl NetworkPoller {
4747

4848
pub(crate) fn poll<'a>(
4949
&self,
50-
events: &'a mut sys::Events,
50+
events: &'a mut Vec<sys::Event>,
5151
) -> impl Iterator<Item = ProcessPointer> + 'a {
5252
events.clear();
5353

@@ -70,7 +70,9 @@ impl NetworkPoller {
7070
source: impl AsFd,
7171
interest: Interest,
7272
) {
73-
self.inner.add(process.identifier() as _, source, interest);
73+
let fd = source.as_fd().as_raw_fd();
74+
75+
self.inner.add(process.identifier() as _, fd, interest);
7476
}
7577

7678
pub(crate) fn modify(
@@ -79,11 +81,15 @@ impl NetworkPoller {
7981
source: impl AsFd,
8082
interest: Interest,
8183
) {
82-
self.inner.modify(process.identifier() as _, source, interest)
84+
let fd = source.as_fd().as_raw_fd();
85+
86+
self.inner.modify(process.identifier() as _, fd, interest)
8387
}
8488

8589
pub(crate) fn delete(&self, source: impl AsFd) {
86-
self.inner.delete(source);
90+
let fd = source.as_fd().as_raw_fd();
91+
92+
self.inner.delete(fd);
8793
}
8894
}
8995

@@ -99,7 +105,7 @@ impl Worker {
99105
}
100106

101107
pub(crate) fn run(&mut self) {
102-
let mut events = sys::Events::with_capacity(CAPACITY);
108+
let mut events = Vec::with_capacity(CAPACITY);
103109
let mut procs = Vec::with_capacity(128);
104110
let poller = &self.state.network_pollers[self.id];
105111

@@ -172,7 +178,7 @@ mod tests {
172178
let poller = NetworkPoller::new();
173179
let typ = empty_process_type("A");
174180
let process = new_process(*typ);
175-
let mut events = sys::Events::with_capacity(1);
181+
let mut events = Vec::with_capacity(1);
176182

177183
poller.add(*process, &output, Interest::Write);
178184

@@ -187,7 +193,7 @@ mod tests {
187193
let poller = NetworkPoller::new();
188194
let typ = empty_process_type("A");
189195
let process = new_process(*typ);
190-
let mut events = sys::Events::with_capacity(1);
196+
let mut events = Vec::with_capacity(1);
191197

192198
let tagged =
193199
unsafe { ProcessPointer::new((process.identifier() | 0b01) as _) };
@@ -207,7 +213,7 @@ mod tests {
207213
let typ = empty_process_type("A");
208214
let proc1 = new_process(*typ);
209215
let proc2 = new_process(*typ);
210-
let mut events = sys::Events::with_capacity(1);
216+
let mut events = Vec::with_capacity(1);
211217

212218
poller.add(*proc1, &sock1, Interest::Write);
213219
poller.add(*proc2, &sock2, Interest::Write);

rt/src/network_poller/epoll.rs

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,102 @@
11
use crate::network_poller::Interest;
2-
use rustix::event::epoll::{
3-
add, create, delete, modify, wait, CreateFlags, EventData, EventFlags,
4-
EventVec,
2+
use libc::{
3+
epoll_create, epoll_ctl, epoll_event, epoll_wait, EPOLLET, EPOLLIN,
4+
EPOLLONESHOT, EPOLLOUT, EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLL_CTL_DEL,
5+
EPOLL_CTL_MOD,
56
};
6-
use rustix::fd::{AsFd, OwnedFd};
7-
use rustix::io::Errno;
7+
use std::ffi::c_int;
8+
use std::io::Error;
9+
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd};
10+
use std::ptr::null_mut;
811

9-
fn flags_for(interest: Interest) -> EventFlags {
12+
fn flags_for(interest: Interest) -> u32 {
1013
let flags = match interest {
11-
Interest::Read => EventFlags::IN,
12-
Interest::Write => EventFlags::OUT,
14+
Interest::Read => EPOLLIN,
15+
Interest::Write => EPOLLOUT,
1316
};
1417

15-
flags | EventFlags::ET | EventFlags::ONESHOT
18+
(flags | EPOLLET | EPOLLONESHOT) as u32
1619
}
1720

18-
pub(crate) type Events = EventVec;
21+
pub(crate) type Event = epoll_event;
1922

2023
pub(crate) struct Poller {
2124
fd: OwnedFd,
2225
}
2326

2427
impl Poller {
2528
pub(crate) fn new() -> Poller {
26-
let fd = create(CreateFlags::CLOEXEC).expect("epoll_create() failed");
29+
let fd = unsafe { epoll_create(EPOLL_CLOEXEC) };
2730

28-
Poller { fd }
31+
if fd == -1 {
32+
panic!("epoll_create() failed");
33+
}
34+
35+
// Safety: we checked the file descriptor so at this point it's
36+
// guaranteed to be valid.
37+
Poller { fd: unsafe { OwnedFd::from_raw_fd(fd) } }
2938
}
3039

3140
pub(crate) fn poll<'a>(
3241
&self,
33-
events: &'a mut Events,
42+
events: &'a mut Vec<Event>,
3443
) -> impl Iterator<Item = u64> + 'a {
35-
match wait(&self.fd, events, -1) {
36-
Ok(_) | Err(Errno::INTR) => {}
37-
Err(_) => panic!("epoll_wait() failed"),
44+
let res = unsafe {
45+
epoll_wait(
46+
self.fd.as_raw_fd(),
47+
events.as_mut_ptr(),
48+
events.capacity() as _,
49+
-1,
50+
)
51+
};
52+
53+
if res == -1 {
54+
panic!("epoll_wait() failed: {}", Error::last_os_error());
3855
}
3956

40-
events.iter().map(|e| e.data.u64())
57+
// Safety: the above check ensures the length value is valid.
58+
unsafe { events.set_len(res as _) };
59+
events.iter().map(|e| e.u64)
4160
}
4261

43-
pub(crate) fn add(&self, id: u64, source: impl AsFd, interest: Interest) {
44-
let data = EventData::new_u64(id);
62+
pub(crate) fn add(
63+
&self,
64+
id: u64,
65+
source: impl AsRawFd,
66+
interest: Interest,
67+
) {
68+
let mut event = epoll_event { events: flags_for(interest), u64: id };
4569

46-
add(&self.fd, source, data, flags_for(interest))
47-
.expect("epoll_ctl() failed");
70+
self.ctl(EPOLL_CTL_ADD, source, Some(&mut event));
4871
}
4972

5073
pub(crate) fn modify(
5174
&self,
5275
id: u64,
53-
source: impl AsFd,
76+
source: impl AsRawFd,
5477
interest: Interest,
5578
) {
56-
let data = EventData::new_u64(id);
79+
let mut event = epoll_event { events: flags_for(interest), u64: id };
80+
81+
self.ctl(EPOLL_CTL_MOD, source, Some(&mut event));
82+
}
5783

58-
modify(&self.fd, source, data, flags_for(interest))
59-
.expect("epoll_ctl() failed");
84+
pub(crate) fn delete(&self, source: impl AsRawFd) {
85+
self.ctl(EPOLL_CTL_DEL, source, None);
6086
}
6187

62-
pub(crate) fn delete(&self, source: impl AsFd) {
63-
delete(&self.fd, source).expect("epoll_ctl() failed");
88+
fn ctl(&self, op: c_int, fd: impl AsRawFd, event: Option<&mut Event>) {
89+
let res = unsafe {
90+
epoll_ctl(
91+
self.fd.as_raw_fd(),
92+
op,
93+
fd.as_raw_fd(),
94+
event.map(|v| v as *mut _).unwrap_or_else(null_mut),
95+
)
96+
};
97+
98+
if res == -1 {
99+
panic!("epoll_ctl() failed: {}", Error::last_os_error());
100+
}
64101
}
65102
}

rt/src/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,8 +732,8 @@ impl DerefMut for ProcessPointer {
732732
#[cfg(test)]
733733
mod tests {
734734
use super::*;
735+
use crate::mem::page_size;
735736
use crate::test::{empty_process_type, OwnedProcess};
736-
use rustix::param::page_size;
737737
use std::mem::size_of;
738738
use std::num::NonZeroU64;
739739

rt/src/result.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustix::io::Errno;
1+
use libc::ETIMEDOUT;
22
use std::io;
33

44
pub(crate) const OK: i64 = 0;
@@ -11,7 +11,7 @@ pub(crate) fn error_to_int(error: io::Error) -> i64 {
1111
} else if let io::ErrorKind::TimedOut = error.kind() {
1212
// Socket deadlines produce a TimedOut manually, in which case
1313
// raw_os_error() above returns a None.
14-
Errno::TIMEDOUT.raw_os_error()
14+
ETIMEDOUT
1515
} else {
1616
match error.kind() {
1717
io::ErrorKind::InvalidData => -2,

rt/src/runtime.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::process::{NativeAsyncMethod, Process};
1717
use crate::scheduler::signal as signal_sched;
1818
use crate::stack::total_stack_size;
1919
use crate::state::{RcState, State};
20-
use rustix::param::page_size;
2120
use std::ffi::CStr;
2221
use std::slice;
2322
use std::thread;
@@ -90,8 +89,10 @@ pub unsafe extern "system" fn inko_runtime_state(
9089
pub unsafe extern "system" fn inko_runtime_stack_mask(
9190
runtime: *mut Runtime,
9291
) -> u64 {
93-
let raw_size = (&(*runtime)).state.config.stack_size;
94-
let total = total_stack_size(raw_size as _, page_size()) as u64;
92+
let rt = &*runtime;
93+
let raw_size = rt.state.config.stack_size;
94+
let page = rt.state.config.page_size;
95+
let total = total_stack_size(raw_size as _, page) as u64;
9596

9697
!(total - 1)
9798
}

0 commit comments

Comments
 (0)