1 //! Solaris/illumos event ports.
2 
3 use crate::backend::c;
4 use crate::backend::event::syscalls;
5 use crate::fd::{AsFd, AsRawFd, OwnedFd};
6 use crate::io;
7 
8 use super::PollFlags;
9 
10 use core::time::Duration;
11 
12 /// The structure representing a port event.
13 #[repr(transparent)]
14 pub struct Event(pub(crate) c::port_event);
15 
16 impl Event {
17     /// Get the events associated with this event.
events(&self) -> i3218     pub fn events(&self) -> i32 {
19         self.0.portev_events
20     }
21 
22     /// Get the event source associated with this event.
object(&self) -> usize23     pub fn object(&self) -> usize {
24         self.0.portev_object
25     }
26 
27     /// Get the userdata associated with this event.
userdata(&self) -> *mut c::c_void28     pub fn userdata(&self) -> *mut c::c_void {
29         self.0.portev_user
30     }
31 }
32 
33 /// `port_create()`—Creates a new port.
34 ///
35 /// # References
36 ///  - [OpenSolaris]
37 ///  - [illumos]
38 ///
39 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_create/
40 /// [illumos]: https://illumos.org/man/3C/port_create
port_create() -> io::Result<OwnedFd>41 pub fn port_create() -> io::Result<OwnedFd> {
42     syscalls::port_create()
43 }
44 
45 /// `port_associate(_, PORT_SOURCE_FD, _, _, _)`—Associates a file descriptor
46 /// with a port.
47 ///
48 /// # Safety
49 ///
50 /// Any `object`s passed into the `port` must be valid for the lifetime of the
51 /// `port`. Logically, `port` keeps a borrowed reference to the `object` until
52 /// it is removed via `port_dissociate_fd`.
53 ///
54 /// # References
55 ///  - [OpenSolaris]
56 ///  - [illumos]
57 ///
58 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_associate/
59 /// [illumos]: https://illumos.org/man/3C/port_associate
port_associate_fd( port: impl AsFd, object: impl AsRawFd, events: PollFlags, userdata: *mut c::c_void, ) -> io::Result<()>60 pub unsafe fn port_associate_fd(
61     port: impl AsFd,
62     object: impl AsRawFd,
63     events: PollFlags,
64     userdata: *mut c::c_void,
65 ) -> io::Result<()> {
66     syscalls::port_associate(
67         port.as_fd(),
68         c::PORT_SOURCE_FD,
69         object.as_raw_fd() as _,
70         events.bits() as _,
71         userdata.cast(),
72     )
73 }
74 
75 /// `port_dissociate(_, PORT_SOURCE_FD, _)`—Dissociates a file descriptor
76 /// from a port.
77 ///
78 /// # Safety
79 ///
80 /// The file descriptor passed into this function must have been previously
81 /// associated with the port via [`port_associate_fd`].
82 ///
83 /// # References
84 ///  - [OpenSolaris]
85 ///  - [illumos]
86 ///
87 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_dissociate
88 /// [illumos]: https://illumos.org/man/3C/port_dissociate
port_dissociate_fd(port: impl AsFd, object: impl AsRawFd) -> io::Result<()>89 pub unsafe fn port_dissociate_fd(port: impl AsFd, object: impl AsRawFd) -> io::Result<()> {
90     syscalls::port_dissociate(port.as_fd(), c::PORT_SOURCE_FD, object.as_raw_fd() as _)
91 }
92 
93 /// `port_get(port, timeout)`—Gets an event from a port.
94 ///
95 /// # References
96 ///  - [OpenSolaris]
97 ///  - [illumos]
98 ///
99 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_get/
100 /// [illumos]: https://illumos.org/man/3C/port_get
port_get(port: impl AsFd, timeout: Option<Duration>) -> io::Result<Event>101 pub fn port_get(port: impl AsFd, timeout: Option<Duration>) -> io::Result<Event> {
102     let mut timeout = timeout.map(|timeout| c::timespec {
103         tv_sec: timeout.as_secs().try_into().unwrap(),
104         tv_nsec: timeout.subsec_nanos() as _,
105     });
106 
107     syscalls::port_get(port.as_fd(), timeout.as_mut())
108 }
109 
110 /// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a
111 /// port.
112 ///
113 /// # References
114 ///  - [OpenSolaris]
115 ///  - [illumos]
116 ///
117 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/
118 /// [illumos]: https://illumos.org/man/3C/port_getn
119 #[cfg(feature = "alloc")]
port_getn( port: impl AsFd, events: &mut Vec<Event>, min_events: usize, timeout: Option<Duration>, ) -> io::Result<()>120 pub fn port_getn(
121     port: impl AsFd,
122     events: &mut Vec<Event>,
123     min_events: usize,
124     timeout: Option<Duration>,
125 ) -> io::Result<()> {
126     events.clear();
127 
128     let mut timeout = timeout.map(|timeout| c::timespec {
129         tv_sec: timeout.as_secs().try_into().unwrap(),
130         tv_nsec: timeout.subsec_nanos() as _,
131     });
132 
133     syscalls::port_getn(
134         port.as_fd(),
135         timeout.as_mut(),
136         events,
137         min_events.try_into().unwrap(),
138     )
139 }
140 
141 /// `port_send(port, events, userdata)`—Sends an event to a port.
142 ///
143 /// # References
144 ///  - [OpenSolaris]
145 ///  - [illumos]
146 ///
147 /// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_send/
148 /// [illumos]: https://illumos.org/man/3C/port_send
port_send(port: impl AsFd, events: i32, userdata: *mut c::c_void) -> io::Result<()>149 pub fn port_send(port: impl AsFd, events: i32, userdata: *mut c::c_void) -> io::Result<()> {
150     syscalls::port_send(port.as_fd(), events, userdata.cast())
151 }
152