瀏覽代碼

Avoid allocations in redox epoll

jD91mZM2 6 年之前
父節點
當前提交
4c8f51ace9
共有 4 個文件被更改,包括 36 次插入15 次删除
  1. 1 0
      src/header/poll/mod.rs
  2. 15 3
      src/header/sys_epoll/mod.rs
  3. 3 0
      src/header/sys_select/mod.rs
  4. 17 12
      src/platform/redox/epoll.rs

+ 1 - 0
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() {

+ 15 - 3
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]

+ 3 - 0
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;

+ 17 - 12
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>());
             }
         }