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