summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs3
-rw-r--r--src/poll.rs80
-rw-r--r--test/test.rs3
-rw-r--r--test/test_poll.rs22
4 files changed, 108 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6b321ba2..8714550b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -31,6 +31,9 @@ pub mod mount;
#[cfg(any(target_os = "linux"))]
pub mod mqueue;
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+pub mod poll;
+
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;
diff --git a/src/poll.rs b/src/poll.rs
new file mode 100644
index 00000000..d43e358b
--- /dev/null
+++ b/src/poll.rs
@@ -0,0 +1,80 @@
+use libc::c_int;
+use {Error, Result};
+use errno::Errno;
+
+pub use self::ffi::PollFd;
+pub use self::ffi::consts::*;
+
+mod ffi {
+ use libc::c_int;
+ pub use self::consts::*;
+
+ #[derive(Clone, Copy, Debug)]
+ #[repr(C)]
+ pub struct PollFd {
+ pub fd: c_int,
+ pub events: EventFlags,
+ pub revents: EventFlags
+ }
+
+ #[cfg(target_os = "linux")]
+ pub mod consts {
+ use libc::{c_short, c_ulong};
+
+ bitflags! {
+ flags EventFlags: c_short {
+ const POLLIN = 0x001,
+ const POLLPRI = 0x002,
+ const POLLOUT = 0x004,
+ const POLLRDNORM = 0x040,
+ const POLLWRNORM = 0x100,
+ const POLLRDBAND = 0x080,
+ const POLLWRBAND = 0x200,
+ const POLLERR = 0x008,
+ const POLLHUP = 0x010,
+ const POLLNVAL = 0x020,
+ }
+ }
+
+ pub type nfds_t = c_ulong;
+ }
+
+ #[cfg(target_os = "macos")]
+ pub mod consts {
+ use libc::{c_short, c_uint};
+
+ bitflags! {
+ flags EventFlags: c_short {
+ const POLLIN = 0x0001,
+ const POLLPRI = 0x0002,
+ const POLLOUT = 0x0004,
+ const POLLRDNORM = 0x0040,
+ const POLLWRNORM = 0x0004,
+ const POLLRDBAND = 0x0080,
+ const POLLWRBAND = 0x0100,
+ const POLLERR = 0x0008,
+ const POLLHUP = 0x0010,
+ const POLLNVAL = 0x0020,
+ }
+ }
+
+ pub type nfds_t = c_uint;
+ }
+
+ #[allow(improper_ctypes)]
+ extern {
+ pub fn poll(fds: *mut PollFd, nfds: nfds_t, timeout: c_int) -> c_int;
+ }
+}
+
+pub fn poll(fds: &mut [PollFd], timeout: c_int) -> Result<c_int> {
+ let res = unsafe {
+ ffi::poll(fds.as_mut_ptr(), fds.len() as ffi::nfds_t, timeout)
+ };
+
+ if res < 0 {
+ return Err(Error::Sys(Errno::last()));
+ }
+
+ Ok(res)
+}
diff --git a/test/test.rs b/test/test.rs
index 52df764f..8d0b6f14 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -14,6 +14,9 @@ mod test_unistd;
#[cfg(any(target_os = "linux"))]
mod test_mq;
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+mod test_poll;
+
mod ports {
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
use std::sync::atomic::Ordering::SeqCst;
diff --git a/test/test_poll.rs b/test/test_poll.rs
new file mode 100644
index 00000000..54fd4029
--- /dev/null
+++ b/test/test_poll.rs
@@ -0,0 +1,22 @@
+use nix::poll::*;
+use nix::unistd::{write, pipe};
+
+#[test]
+fn test_poll() {
+ let (r, w) = pipe().unwrap();
+ let mut fds = [PollFd {
+ fd: r,
+ events: POLLIN,
+ revents: EventFlags::empty()
+ }];
+
+ let nfds = poll(&mut fds, 100).unwrap();
+ assert_eq!(nfds, 0);
+ assert!(!fds[0].revents.contains(POLLIN));
+
+ write(w, b".").unwrap();
+
+ let nfds = poll(&mut fds, 100).unwrap();
+ assert_eq!(nfds, 1);
+ assert!(fds[0].revents.contains(POLLIN));
+}