diff --git a/src/header/sys_epoll/linux.rs b/src/header/sys_epoll/linux.rs
index af4972e7006f0365147d6c408ae6a27e53c3ebf7..654d4ff5cea04ac946b47da3ca6485f0d4ac5d9c 100644
--- a/src/header/sys_epoll/linux.rs
+++ b/src/header/sys_epoll/linux.rs
@@ -1,3 +1,20 @@
 use platform::types::*;
 
 pub const EPOLL_CLOEXEC: c_int = 0x8_0000;
+
+pub const EPOLLIN: c_uint = 0x001;
+pub const EPOLLPRI: c_uint = 0x002;
+pub const EPOLLOUT: c_uint = 0x004;
+pub const EPOLLRDNORM: c_uint = 0x040;
+pub const EPOLLNVAL: c_uint = 0x020;
+pub const EPOLLRDBAND: c_uint = 0x080;
+pub const EPOLLWRNORM: c_uint = 0x100;
+pub const EPOLLWRBAND: c_uint = 0x200;
+pub const EPOLLMSG: c_uint = 0x400;
+pub const EPOLLERR: c_uint = 0x008;
+pub const EPOLLHUP: c_uint = 0x010;
+pub const EPOLLRDHUP: c_uint = 0x2000;
+pub const EPOLLEXCLUSIVE: c_uint = 1 << 28;
+pub const EPOLLWAKEUP: c_uint = 1 << 29;
+pub const EPOLLONESHOT: c_uint = 1 << 30;
+pub const EPOLLET: c_uint = 1 << 31;
diff --git a/src/header/sys_epoll/mod.rs b/src/header/sys_epoll/mod.rs
index 06893bc0aa45d61fee2ebfe8ed7bf0b852fa85d3..cdde02441d5616acee0a8b26d4a1ca5cffb0e187 100644
--- a/src/header/sys_epoll/mod.rs
+++ b/src/header/sys_epoll/mod.rs
@@ -20,31 +20,32 @@ pub const EPOLL_CTL_ADD: c_int = 1;
 pub const EPOLL_CTL_DEL: c_int = 2;
 pub const EPOLL_CTL_MOD: c_int = 3;
 
-pub const EPOLLIN: u32 =     0x0001;
-pub const EPOLLPRI: u32 =    0x0002;
-pub const EPOLLOUT: u32 =    0x0004;
-pub const EPOLLERR: u32 =    0x0008;
-pub const EPOLLHUP: u32 =    0x0010;
-pub const EPOLLNVAL: u32 =   0x0020;
-pub const EPOLLRDNORM: u32 = 0x0040;
-pub const EPOLLRDBAND: u32 = 0x0080;
-pub const EPOLLWRNORM: u32 = 0x0100;
-pub const EPOLLWRBAND: u32 = 0x0200;
-pub const EPOLLMSG: u32 =    0x0400;
-pub const EPOLLRDHUP: u32 =  0x2000;
-
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union epoll_data {
     pub ptr: *mut c_void,
     pub fd: c_int,
     pub u32: u32,
     pub u64: u64,
 }
+impl Default for epoll_data {
+    fn default() -> Self {
+        Self { u64: 0 }
+    }
+}
 
 #[repr(C)]
+#[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_epoll/redox.rs b/src/header/sys_epoll/redox.rs
index 870f7f9d9f9c4864ca6fb158276313c8397c8bb7..d1172fbb35e4c5745e0f21f78e87cc73e958596c 100644
--- a/src/header/sys_epoll/redox.rs
+++ b/src/header/sys_epoll/redox.rs
@@ -1,3 +1,20 @@
 use platform::types::*;
 
 pub const EPOLL_CLOEXEC: c_int = 0x0100_0000;
+
+pub const EPOLLIN: c_uint = 1;
+pub const EPOLLPRI: c_uint = 0;
+pub const EPOLLOUT: c_uint = 2;
+pub const EPOLLRDNORM: c_uint = 0;
+pub const EPOLLNVAL: c_uint = 0;
+pub const EPOLLRDBAND: c_uint = 0;
+pub const EPOLLWRNORM: c_uint = 0;
+pub const EPOLLWRBAND: c_uint = 0;
+pub const EPOLLMSG: c_uint = 0;
+pub const EPOLLERR: c_uint = 0;
+pub const EPOLLHUP: c_uint = 0;
+pub const EPOLLRDHUP: c_uint = 0;
+pub const EPOLLEXCLUSIVE: c_uint = 0;
+pub const EPOLLWAKEUP: c_uint = 0;
+pub const EPOLLONESHOT: c_uint = 0;
+pub const EPOLLET: c_uint = 0;
diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs
new file mode 100644
index 0000000000000000000000000000000000000000..03e3f591a8a1e13e44124f8e04341a9c54b0ee36
--- /dev/null
+++ b/src/platform/redox/epoll.rs
@@ -0,0 +1,91 @@
+use super::super::types::*;
+use super::super::{Pal, PalEpoll};
+use super::Sys;
+
+use c_str::CStr;
+use core::{mem, slice};
+use fs::File;
+use io::prelude::*;
+use header::errno::*;
+use header::fcntl::*;
+use header::signal::sigset_t;
+use header::sys_epoll::*;
+use syscall::data::{Event, TimeSpec};
+use syscall::flag::EVENT_READ;
+
+impl PalEpoll for Sys {
+    fn epoll_create1(flags: c_int) -> c_int {
+        Sys::open(
+            CStr::from_bytes_with_nul(b"event:\0").unwrap(),
+            O_RDWR | flags,
+            0
+        )
+    }
+
+    fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int {
+        Sys::write(epfd, &Event {
+            id: fd 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 _timer;
+        if timeout != -1 {
+            _timer = File::open(CStr::from_bytes_with_nul(b"time:\0").unwrap(), O_RDWR);
+            match _timer {
+                Err(_) => return -1,
+                Ok(mut timer) => {
+                    let mut time = TimeSpec::default();
+                    if let Err(err) = timer.read(&mut time) {
+                        return -1;
+                    }
+                    time.tv_nsec += timeout;
+                    if let Err(err) = timer.write(&time) {
+                        return -1;
+                    }
+
+                    if Sys::write(epfd, &Event {
+                        id: timer.fd as usize,
+                        flags: EVENT_READ,
+                        data: 0
+                    }) == -1 {
+                        return -1;
+                    }
+                }
+            }
+        }
+
+        let bytes_read = Sys::read(epfd, unsafe { slice::from_raw_parts_mut(
+            events as *mut u8,
+            maxevents as usize
+        ) });
+        if bytes_read == -1 {
+            return -1;
+        }
+        let read = bytes_read as usize / mem::size_of::<Event>();
+
+        for i in 0..maxevents {
+            unsafe {
+                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>());
+            }
+        }
+
+        read as c_int
+    }
+}
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index b3293534f75d85a6d4a31d486643de1164195348..9da86dd9d9441c73abb508f877e5fdf484f26549 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -1,6 +1,5 @@
 //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
 
-use cbitset::BitSet;
 use core::result::Result as CoreResult;
 use core::{mem, ptr, slice};
 use syscall::data::Map;
@@ -27,6 +26,7 @@ use io::{self, BufReader, SeekFrom};
 use super::types::*;
 use super::{errno, Pal, Read};
 
+mod epoll;
 mod extra;
 mod signal;
 mod socket;
@@ -679,7 +679,7 @@ impl Pal for Sys {
         )) as c_int
     }
 
-    fn pipe(fds: &mut [c_int], flags: c_int) -> c_int {
+    fn pipe2(fds: &mut [c_int], flags: c_int) -> c_int {
         let mut usize_fds: [usize; 2] = [0; 2];
         let res = e(syscall::pipe2(&mut usize_fds, flags as usize));
         fds[0] = usize_fds[0] as c_int;
@@ -687,135 +687,6 @@ impl Pal for Sys {
         res as c_int
     }
 
-    fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
-        let fds = unsafe { slice::from_raw_parts_mut(fds, nfds as usize) };
-
-        let event_path = c_str!("event:");
-        let mut event_file = match File::open(event_path, fcntl::O_RDWR | fcntl::O_CLOEXEC) {
-            Ok(file) => file,
-            Err(_) => return -1,
-        };
-
-        for fd in fds.iter_mut() {
-            let mut flags = 0;
-
-            if fd.events & poll::POLLIN > 0 {
-                flags |= syscall::EVENT_READ;
-            }
-
-            if fd.events & poll::POLLOUT > 0 {
-                flags |= syscall::EVENT_WRITE;
-            }
-
-            fd.revents = 0;
-
-            if fd.fd >= 0 && flags > 0 {
-                if event_file
-                    .write(&syscall::Event {
-                        id: fd.fd as usize,
-                        flags: flags,
-                        data: 0,
-                    })
-                    .is_err()
-                {
-                    return -1;
-                }
-            }
-        }
-
-        const TIMEOUT_TOKEN: usize = 1;
-
-        let timeout_file = if timeout < 0 {
-            None
-        } else {
-            let timeout_path = unsafe {
-                CString::from_vec_unchecked(
-                    format!("time:{}", syscall::CLOCK_MONOTONIC).into_bytes(),
-                )
-            };
-            let mut timeout_file = match File::open(&timeout_path, fcntl::O_RDWR | fcntl::O_CLOEXEC)
-            {
-                Ok(file) => file,
-                Err(_) => return -1,
-            };
-
-            if event_file
-                .write(&syscall::Event {
-                    id: *timeout_file as usize,
-                    flags: syscall::EVENT_READ,
-                    data: TIMEOUT_TOKEN,
-                })
-                .is_err()
-            {
-                return -1;
-            }
-
-            let mut time = syscall::TimeSpec::default();
-            if timeout_file.read(&mut time).is_err() {
-                return -1;
-            }
-
-            time.tv_nsec += timeout * 1000000;
-            while time.tv_nsec >= 1000000000 {
-                time.tv_sec += 1;
-                time.tv_nsec -= 1000000000;
-            }
-
-            // Teehee
-            if timeout == 0 {
-                time.tv_sec += 1;
-            }
-
-            if timeout_file.write(&time).is_err() {
-                return -1;
-            }
-
-            Some(timeout_file)
-        };
-
-        let mut events = [syscall::Event::default(); 32];
-        let read = {
-            let mut events = unsafe {
-                slice::from_raw_parts_mut(
-                    &mut events as *mut _ as *mut u8,
-                    mem::size_of::<syscall::Event>() * events.len(),
-                )
-            };
-            match event_file.read(&mut events) {
-                Ok(i) => i / mem::size_of::<syscall::Event>(),
-                Err(_) => return -1,
-            }
-        };
-
-        for event in &events[..read] {
-            if event.data == TIMEOUT_TOKEN {
-                continue;
-            }
-
-            for fd in fds.iter_mut() {
-                if event.id == fd.fd as usize {
-                    if event.flags & syscall::EVENT_READ > 0 {
-                        fd.revents |= poll::POLLIN;
-                    }
-
-                    if event.flags & syscall::EVENT_WRITE > 0 {
-                        fd.revents |= poll::POLLOUT;
-                    }
-                }
-            }
-        }
-
-        let mut total = 0;
-
-        for fd in fds.iter_mut() {
-            if fd.revents > 0 {
-                total += 1;
-            }
-        }
-
-        total
-    }
-
     #[cfg(target_arch = "x86_64")]
     unsafe fn pte_clone(stack: *mut usize) -> pid_t {
         let flags = syscall::CLONE_VM