From 4c8f51ace98818a527ff1b7fcf68c458dfb16a9f Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Sun, 28 Apr 2019 14:51:42 +0200 Subject: [PATCH] Avoid allocations in redox epoll --- src/header/poll/mod.rs | 1 + src/header/sys_epoll/mod.rs | 18 +++++++++++++++--- src/header/sys_select/mod.rs | 3 +++ src/platform/redox/epoll.rs | 29 +++++++++++++++++------------ 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/header/poll/mod.rs b/src/header/poll/mod.rs index 4d6f9e41..e8d9cba6 100644 --- a/src/header/poll/mod.rs +++ b/src/header/poll/mod.rs @@ -54,6 +54,7 @@ pub fn poll_epoll(fds: &mut [pollfd], timeout: c_int) -> c_int { data: epoll_data { u64: i as u64, }, + ..Default::default() }; for (p, ep) in event_map.iter() { diff --git a/src/header/sys_epoll/mod.rs b/src/header/sys_epoll/mod.rs index ab8e4fc0..cdde0244 100644 --- a/src/header/sys_epoll/mod.rs +++ b/src/header/sys_epoll/mod.rs @@ -28,12 +28,24 @@ pub union epoll_data { pub u32: u32, pub u64: u64, } +impl Default for epoll_data { + fn default() -> Self { + Self { u64: 0 } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] +// This will match in size with syscall::Event (24 bytes on 64-bit +// systems) on redox. The `Default` trait is here so we don't need to +// worry about the padding when using this type. pub struct epoll_event { - pub events: u32, - pub data: epoll_data, + pub events: u32, // 4 bytes + // 4 automatic alignment bytes + pub data: epoll_data, // 8 bytes + + #[cfg(target_os = "redox")] + pub _pad: u64, // 8 bytes } #[no_mangle] diff --git a/src/header/sys_select/mod.rs b/src/header/sys_select/mod.rs index bf77b819..c87ad6ee 100644 --- a/src/header/sys_select/mod.rs +++ b/src/header/sys_select/mod.rs @@ -80,6 +80,7 @@ pub fn select_epoll( data: epoll_data { fd: fd, }, + ..Default::default() }; if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 { return -1; @@ -93,6 +94,7 @@ pub fn select_epoll( data: epoll_data { fd: fd, }, + ..Default::default() }; if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 { return -1; @@ -106,6 +108,7 @@ pub fn select_epoll( data: epoll_data { fd: fd, }, + ..Default::default() }; if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 { return -1; diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs index c266e463..03e3f591 100644 --- a/src/platform/redox/epoll.rs +++ b/src/platform/redox/epoll.rs @@ -23,19 +23,19 @@ impl PalEpoll for Sys { } fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int { - let flags = unsafe { (*event).events }; Sys::write(epfd, &Event { id: fd as usize, - flags: flags as usize, - data: event as usize + flags: unsafe { (*event).events as usize }, + + // NOTE: Danger when using non 64-bit systems. If this is + // needed, use a box or something + data: unsafe { mem::transmute((*event).data) } }) as c_int } fn epoll_pwait(epfd: c_int, mut events: *mut epoll_event, maxevents: c_int, timeout: c_int, _sigset: *const sigset_t) -> c_int { // TODO: sigset - let mut redox_events = vec![Event::default(); maxevents as usize]; - let _timer; if timeout != -1 { _timer = File::open(CStr::from_bytes_with_nul(b"time:\0").unwrap(), O_RDWR); @@ -63,20 +63,25 @@ impl PalEpoll for Sys { } let bytes_read = Sys::read(epfd, unsafe { slice::from_raw_parts_mut( - redox_events.as_mut_ptr() as *mut u8, - redox_events.len() * mem::size_of::<Event>() + events as *mut u8, + maxevents as usize ) }); if bytes_read == -1 { return -1; } let read = bytes_read as usize / mem::size_of::<Event>(); - for event in &redox_events { - if event.data == 0 { - return EINTR; - } + for i in 0..maxevents { unsafe { - *events = *(event.data as *mut epoll_event); + let event = *(events as *mut Event); + if event.data == 0 { + return EINTR; + } + *events = epoll_event { + events: event.flags as _, + data: mem::transmute(event.data), + ..Default::default() + }; events = events.add(mem::size_of::<epoll_event>()); } } -- GitLab