@@ -24,17 +24,17 @@ pub struct FdSet {
2424}
2525
2626impl FdSet {
27- fn iter_fds ( & self , max : i32 ) -> impl Iterator < Item = Fd > {
28- let mut candidate_fd = 0 ;
27+ fn iter_fds ( & self , max : usize ) -> impl Iterator < Item = Fd > {
28+ let mut candidate_fd = 0usize ;
2929
3030 iter:: from_fn ( move || {
3131 loop {
3232 if candidate_fd == max {
3333 return None ;
3434 }
3535
36- if self . set [ candidate_fd as usize / 64 ] & ( 1 << ( candidate_fd % 64 ) ) != 0 {
37- let ret = Fd ( candidate_fd) ;
36+ if self . set [ candidate_fd / 64 ] & ( 1 << ( candidate_fd % 64 ) ) != 0 {
37+ let ret = Fd ( candidate_fd as i32 ) ;
3838 candidate_fd += 1 ;
3939
4040 return Some ( ret) ;
@@ -58,71 +58,113 @@ impl FdSet {
5858
5959unsafe impl UserCopyable for FdSet { }
6060
61- // TODO: handle exceptfds
61+ #[ repr( C ) ]
62+ #[ derive( Clone , Copy , Debug ) ]
63+ pub ( crate ) struct PSelect6SigMask {
64+ sigmask : TUA < SigSet > ,
65+ sigsetsize : usize ,
66+ }
67+
68+ unsafe impl UserCopyable for PSelect6SigMask { }
69+
70+ // TODO: handle exceptfds readiness semantics.
6271pub async fn sys_pselect6 (
6372 ctx : & ProcessCtx ,
6473 max : i32 ,
6574 readfds : TUA < FdSet > ,
6675 writefds : TUA < FdSet > ,
67- _exceptfds : TUA < FdSet > ,
76+ exceptfds : TUA < FdSet > ,
6877 timeout : TUA < TimeSpec > ,
69- mask : TUA < SigSet > ,
78+ mask : TUA < PSelect6SigMask > ,
7079) -> Result < usize > {
80+ if max < 0 || max as usize > SET_SIZE {
81+ return Err ( KernelError :: InvalidValue ) ;
82+ }
83+
84+ let max = max as usize ;
7185 let task = ctx. shared ( ) ;
7286
73- let mut read_fd_set = copy_from_user ( readfds) . await ?;
87+ let mut read_fd_set = if readfds. is_null ( ) {
88+ None
89+ } else {
90+ Some ( copy_from_user ( readfds) . await ?)
91+ } ;
7492
7593 let mut read_fds = Vec :: new ( ) ;
7694
77- let mut write_fd_set = copy_from_user ( writefds) . await ?;
95+ let mut write_fd_set = if writefds. is_null ( ) {
96+ None
97+ } else {
98+ Some ( copy_from_user ( writefds) . await ?)
99+ } ;
78100
79101 let mut write_fds = Vec :: new ( ) ;
80102
103+ let mut except_fd_set = if exceptfds. is_null ( ) {
104+ None
105+ } else {
106+ Some ( copy_from_user ( exceptfds) . await ?)
107+ } ;
108+
81109 let mut timeout_fut = if timeout. is_null ( ) {
82110 None
83111 } else {
84112 let duration = copy_from_user ( timeout) . await ?. into ( ) ;
85113 Some ( pin ! ( sleep( duration) ) )
86114 } ;
87115
88- for fd in read_fd_set. iter_fds ( max) {
89- let file = task
90- . fd_table
91- . lock_save_irq ( )
92- . get ( fd)
93- . ok_or ( KernelError :: BadFd ) ?;
94-
95- read_fds. push ( (
96- Box :: pin ( async move {
97- let ( ops, _) = & mut * file. lock ( ) . await ;
98-
99- ops. poll_read_ready ( ) . await
100- } ) ,
101- fd,
102- ) ) ;
116+ if let Some ( ref read_fd_set) = read_fd_set {
117+ for fd in read_fd_set. iter_fds ( max) {
118+ let file = task
119+ . fd_table
120+ . lock_save_irq ( )
121+ . get ( fd)
122+ . ok_or ( KernelError :: BadFd ) ?;
123+
124+ read_fds. push ( (
125+ Box :: pin ( async move {
126+ let ( ops, _) = & mut * file. lock ( ) . await ;
127+
128+ ops. poll_read_ready ( ) . await
129+ } ) ,
130+ fd,
131+ ) ) ;
132+ }
103133 }
104134
105- for fd in write_fd_set. iter_fds ( max) {
106- let file = task
107- . fd_table
108- . lock_save_irq ( )
109- . get ( fd)
110- . ok_or ( KernelError :: BadFd ) ?;
111-
112- write_fds. push ( (
113- Box :: pin ( async move {
114- let ( ops, _) = & mut * file. lock ( ) . await ;
115-
116- ops. poll_write_ready ( ) . await
117- } ) ,
118- fd,
119- ) ) ;
135+ if let Some ( ref write_fd_set) = write_fd_set {
136+ for fd in write_fd_set. iter_fds ( max) {
137+ let file = task
138+ . fd_table
139+ . lock_save_irq ( )
140+ . get ( fd)
141+ . ok_or ( KernelError :: BadFd ) ?;
142+
143+ write_fds. push ( (
144+ Box :: pin ( async move {
145+ let ( ops, _) = & mut * file. lock ( ) . await ;
146+
147+ ops. poll_write_ready ( ) . await
148+ } ) ,
149+ fd,
150+ ) ) ;
151+ }
120152 }
121153
122154 let mask = if mask. is_null ( ) {
123155 None
124156 } else {
125- Some ( copy_from_user ( mask) . await ?)
157+ let args: PSelect6SigMask = copy_from_user ( mask) . await ?;
158+
159+ if args. sigsetsize != core:: mem:: size_of :: < SigSet > ( ) {
160+ return Err ( KernelError :: InvalidValue ) ;
161+ }
162+
163+ if args. sigmask . is_null ( ) {
164+ None
165+ } else {
166+ Some ( copy_from_user ( args. sigmask ) . await ?)
167+ }
126168 } ;
127169 let old_sigmask = task. sig_mask . load ( ) ;
128170 if let Some ( mask) = mask {
@@ -131,24 +173,35 @@ pub async fn sys_pselect6(
131173 task. sig_mask . store ( new_sigmask) ;
132174 }
133175
134- read_fd_set. zero ( ) ;
135- write_fd_set. zero ( ) ;
176+ if let Some ( ref mut read_fd_set) = read_fd_set {
177+ read_fd_set. zero ( ) ;
178+ }
179+ if let Some ( ref mut write_fd_set) = write_fd_set {
180+ write_fd_set. zero ( ) ;
181+ }
182+ if let Some ( ref mut except_fd_set) = except_fd_set {
183+ except_fd_set. zero ( ) ;
184+ }
136185
137186 let n = poll_fn ( |cx| {
138187 let mut num_ready: usize = 0 ;
139188
140189 for ( fut, fd) in read_fds. iter_mut ( ) {
141190 if fut. as_mut ( ) . poll ( cx) . is_ready ( ) {
142191 // Mark the is_ready bool. Don't break out of the loop just
143- // yet, we may aswell check all fds while we're here.
144- read_fd_set. set_fd ( * fd) ;
192+ // yet, we may as well check all fds while we're here.
193+ if let Some ( ref mut read_fd_set) = read_fd_set {
194+ read_fd_set. set_fd ( * fd) ;
195+ }
145196 num_ready += 1 ;
146197 }
147198 }
148199
149200 for ( fut, fd) in write_fds. iter_mut ( ) {
150201 if fut. as_mut ( ) . poll ( cx) . is_ready ( ) {
151- write_fd_set. set_fd ( * fd) ;
202+ if let Some ( ref mut write_fd_set) = write_fd_set {
203+ write_fd_set. set_fd ( * fd) ;
204+ }
152205 num_ready += 1 ;
153206 }
154207 }
@@ -166,12 +219,30 @@ pub async fn sys_pselect6(
166219 } )
167220 . await ;
168221
169- copy_to_user ( readfds, read_fd_set) . await ?;
170- copy_to_user ( writefds, write_fd_set) . await ?;
222+ let readfds_copy_result = if let Some ( read_fd_set) = read_fd_set {
223+ copy_to_user ( readfds, read_fd_set) . await
224+ } else {
225+ Ok ( ( ) )
226+ } ;
227+ let writefds_copy_result = if let Some ( write_fd_set) = write_fd_set {
228+ copy_to_user ( writefds, write_fd_set) . await
229+ } else {
230+ Ok ( ( ) )
231+ } ;
232+ let exceptfds_copy_result = if let Some ( except_fd_set) = except_fd_set {
233+ copy_to_user ( exceptfds, except_fd_set) . await
234+ } else {
235+ Ok ( ( ) )
236+ } ;
237+
171238 if mask. is_some ( ) {
172239 task. sig_mask . store ( old_sigmask) ;
173240 }
174241
242+ readfds_copy_result?;
243+ writefds_copy_result?;
244+ exceptfds_copy_result?;
245+
175246 Ok ( n)
176247}
177248
0 commit comments