@@ -244,57 +244,72 @@ impl Driver {
244244 Poll :: Pending
245245 }
246246 Decision :: Completed ( res) => Poll :: Ready ( Ok ( res) ) ,
247- Decision :: Blocking => loop {
248- if self . push_blocking ( user_data) {
249- break Poll :: Pending ;
250- } else {
251- self . poll_blocking ( ) ;
252- }
253- } ,
247+ Decision :: Blocking => self . push_blocking ( user_data) ,
254248 #[ cfg( aio) ]
255249 Decision :: Aio ( AioControl { mut aiocbp, submit } ) => {
256250 let aiocb = unsafe { aiocbp. as_mut ( ) } ;
257- // sigev_notify_kqueue
258- aiocb. aio_sigevent . sigev_signo = self . poll . as_raw_fd ( ) ;
259- aiocb. aio_sigevent . sigev_notify = libc:: SIGEV_KEVENT ;
260- aiocb. aio_sigevent . sigev_value . sival_ptr = user_data as _ ;
251+ #[ cfg( freebsd) ]
252+ {
253+ // sigev_notify_kqueue
254+ aiocb. aio_sigevent . sigev_signo = self . poll . as_raw_fd ( ) ;
255+ aiocb. aio_sigevent . sigev_notify = libc:: SIGEV_KEVENT ;
256+ aiocb. aio_sigevent . sigev_value . sival_ptr = user_data as _ ;
257+ }
258+ #[ cfg( solarish) ]
259+ let mut notify = libc:: port_notify {
260+ portnfy_port : self . poll . as_raw_fd ( ) ,
261+ portnfy_user : user_data as _ ,
262+ } ;
263+ #[ cfg( solarish) ]
264+ {
265+ aiocb. aio_sigevent . sigev_notify = libc:: SIGEV_PORT ;
266+ aiocb. aio_sigevent . sigev_value . sival_ptr = & mut notify as * mut _ as _ ;
267+ }
261268 match syscall ! ( submit( aiocbp. as_ptr( ) ) ) {
262269 Ok ( _) => Poll :: Pending ,
270+ // FreeBSD:
271+ // * EOPNOTSUPP: It's on a filesystem without AIO support. Just fallback to
272+ // blocking IO.
273+ // * EAGAIN: The process-wide queue is full. No safe way to remove the (maybe)
274+ // dead entries.
275+ // Solarish:
276+ // * EAGAIN: Allocation failed.
263277 Err ( e)
264278 if matches ! (
265279 e. raw_os_error( ) ,
266280 Some ( libc:: EOPNOTSUPP ) | Some ( libc:: EAGAIN )
267281 ) =>
268282 {
269- loop {
270- if self . push_blocking ( user_data) {
271- return Poll :: Pending ;
272- } else {
273- self . poll_blocking ( ) ;
274- }
275- }
283+ self . push_blocking ( user_data)
276284 }
277285 Err ( e) => Poll :: Ready ( Err ( e) ) ,
278286 }
279287 }
280288 }
281289 }
282290
283- fn push_blocking ( & mut self , user_data : usize ) -> bool {
291+ fn push_blocking ( & mut self , user_data : usize ) -> Poll < io :: Result < usize > > {
284292 let poll = self . poll . clone ( ) ;
285293 let completed = self . pool_completed . clone ( ) ;
286- self . pool
287- . dispatch ( move || {
288- let mut op = unsafe { Key :: < dyn crate :: sys:: OpCode > :: new_unchecked ( user_data) } ;
289- let op_pin = op. as_op_pin ( ) ;
290- let res = match op_pin. operate ( ) {
291- Poll :: Pending => unreachable ! ( "this operation is not non-blocking" ) ,
292- Poll :: Ready ( res) => res,
293- } ;
294- completed. push ( Entry :: new ( user_data, res) ) ;
295- poll. notify ( ) . ok ( ) ;
296- } )
297- . is_ok ( )
294+ let mut closure = move || {
295+ let mut op = unsafe { Key :: < dyn crate :: sys:: OpCode > :: new_unchecked ( user_data) } ;
296+ let op_pin = op. as_op_pin ( ) ;
297+ let res = match op_pin. operate ( ) {
298+ Poll :: Pending => unreachable ! ( "this operation is not non-blocking" ) ,
299+ Poll :: Ready ( res) => res,
300+ } ;
301+ completed. push ( Entry :: new ( user_data, res) ) ;
302+ poll. notify ( ) . ok ( ) ;
303+ } ;
304+ loop {
305+ match self . pool . dispatch ( closure) {
306+ Ok ( ( ) ) => return Poll :: Pending ,
307+ Err ( e) => {
308+ closure = e. 0 ;
309+ self . poll_blocking ( ) ;
310+ }
311+ }
312+ }
298313 }
299314
300315 fn poll_blocking ( & mut self ) {
0 commit comments