forked from tokio-rs/mio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial support for Solaris even port API:
- Loading branch information
Showing
2 changed files
with
175 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
use crate::{Interests, Token}; | ||
|
||
use libc::{POLLIN, POLLOUT}; | ||
use log::error; | ||
use std::os::unix::io::{AsRawFd, RawFd}; | ||
#[cfg(debug_assertions)] | ||
use std::sync::atomic::{AtomicUsize, Ordering}; | ||
use std::time::Duration; | ||
use std::{cmp, io, ptr}; | ||
|
||
/// Unique id for use as `SelectorId`. | ||
#[cfg(debug_assertions)] | ||
static NEXT_ID: AtomicUsize = AtomicUsize::new(1); | ||
|
||
#[derive(Debug)] | ||
pub struct Selector { | ||
#[cfg(debug_assertions)] | ||
id: usize, | ||
ep: RawFd, | ||
} | ||
|
||
impl Selector { | ||
pub fn new() -> io::Result<Selector> { | ||
syscall!(port_create()).map(|ep| Selector { | ||
#[cfg(debug_assertions)] | ||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed), | ||
ep, | ||
}) | ||
} | ||
|
||
#[cfg(debug_assertions)] | ||
pub fn id(&self) -> usize { | ||
self.id | ||
} | ||
|
||
pub fn try_clone(&self) -> io::Result<Selector> { | ||
return syscall!(dup(self.ep)).map(|ep| Selector { | ||
// It's the same selector, so we use the same id. | ||
#[cfg(debug_assertions)] | ||
id: 0, | ||
ep, | ||
}) | ||
} | ||
|
||
pub fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> { | ||
let timeout = timeout.map(|to| libc::timespec { | ||
tv_sec: cmp::min(to.as_secs(), libc::time_t::max_value() as u64) as libc::time_t, | ||
// `Duration::subsec_nanos` is guaranteed to be less than one | ||
// billion (the number of nanoseconds in a second), making the | ||
// cast to i32 safe. The cast itself is needed for platforms | ||
// where C's long is only 32 bits. | ||
tv_nsec: libc::c_long::from(to.subsec_nanos() as i32), | ||
}); | ||
let timeout = timeout | ||
.as_ref() | ||
.map(|s| s as *const _) | ||
.unwrap_or(ptr::null_mut()); | ||
|
||
let mut nget = 1 as u32; | ||
|
||
events.clear(); | ||
syscall!(port_getn(self.ep, events.as_mut_ptr(), events.capacity() as u32, &mut nget as *mut u32, timeout)) | ||
.map(|_| { | ||
// This is safe because `epoll_wait` ensures that `n_events` are | ||
// assigned. | ||
unsafe { events.set_len(nget as usize) }; | ||
}) | ||
} | ||
|
||
pub fn register(&self, fd: RawFd, token: Token, interests: Interests) -> io::Result<()> { | ||
|
||
// PORT_SOURCE_FD is 4 | ||
syscall!(port_associate(self.ep, 4, fd as usize, interests_to_evport(interests), usize::from(token) as *mut libc::c_void)).map(|_| ()) | ||
} | ||
|
||
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interests) -> io::Result<()> { | ||
|
||
// PORT_SOURCE_FD is 4 | ||
syscall!(port_associate(self.ep, 4, fd as usize, interests_to_evport(interests), usize::from(token) as *mut libc::c_void)).map(|_| ()) | ||
} | ||
|
||
pub fn deregister(&self, fd: RawFd) -> io::Result<()> { | ||
// PORT_SOURCE_FD is 4 | ||
syscall!(port_dissociate(self.ep, 4, fd as usize)).map(|_| ()) | ||
} | ||
} | ||
|
||
fn interests_to_evport(interests: Interests) -> i32 { | ||
let mut kind = 0; | ||
|
||
if interests.is_readable() { | ||
kind = kind | POLLIN; | ||
} | ||
|
||
if interests.is_writable() { | ||
kind |= POLLOUT; | ||
} | ||
|
||
kind as i32 | ||
} | ||
|
||
impl AsRawFd for Selector { | ||
fn as_raw_fd(&self) -> RawFd { | ||
self.ep | ||
} | ||
} | ||
|
||
impl Drop for Selector { | ||
fn drop(&mut self) { | ||
if let Err(err) = syscall!(close(self.ep)) { | ||
error!("error closing evport: {}", err); | ||
} | ||
} | ||
} | ||
|
||
pub type Event = libc::port_event; | ||
pub type Events = Vec<Event>; | ||
|
||
pub mod event { | ||
use crate::sys::Event; | ||
use crate::Token; | ||
|
||
pub fn token(event: &Event) -> Token { | ||
// Token(event.portev_object as usize) | ||
Token(event.portev_events as usize) | ||
} | ||
|
||
pub fn is_readable(event: &Event) -> bool { | ||
(event.portev_events as libc::c_short & libc::POLLIN) != 0 | ||
|| (event.portev_events as libc::c_short & libc::POLLPRI) != 0 | ||
} | ||
|
||
pub fn is_writable(event: &Event) -> bool { | ||
(event.portev_events as libc::c_short & libc::POLLOUT) != 0 | ||
} | ||
|
||
pub fn is_error(event: &Event) -> bool { | ||
(event.portev_events as libc::c_short & libc::POLLERR) != 0 | ||
} | ||
|
||
pub fn is_read_closed(event: &Event) -> bool { | ||
// Both halves of the socket have closed | ||
event.portev_events as libc::c_short & libc::POLLHUP != 0 | ||
} | ||
|
||
pub fn is_write_closed(event: &Event) -> bool { | ||
// Both halves of the socket have closed | ||
event.portev_events as libc::c_short & libc::POLLHUP != 0 | ||
// Unix pipe write end has closed | ||
|| (event.portev_events as libc::c_short & libc::POLLOUT != 0 | ||
&& event.portev_events as libc::c_short & libc::POLLERR != 0) | ||
} | ||
|
||
pub fn is_priority(event: &Event) -> bool { | ||
(event.portev_events as libc::c_short & libc::POLLPRI) != 0 | ||
} | ||
|
||
pub fn is_aio(_: &Event) -> bool { | ||
// Not supported in the kernel, only in libc. | ||
false | ||
} | ||
|
||
pub fn is_lio(_: &Event) -> bool { | ||
// Not supported. | ||
false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters