@@ -39,14 +39,16 @@ pub fn write(fd: usize, buffer: &[u8]) -> Result<usize, SyscallError> {
3939 . get_handle ( fd)
4040 . ok_or ( SyscallError :: EBADFD ) ?;
4141
42- if handle
43- . flags
44- . intersects ( OpenFlags :: O_WRONLY | OpenFlags :: O_RDWR )
45- {
46- Ok ( handle. write ( buffer) ?)
47- } else {
48- Err ( SyscallError :: EACCES )
49- }
42+ // FIXME(heck for xeyes): fnctl should update the open flags!
43+ //
44+ // if handle
45+ // .flags
46+ // .intersects(OpenFlags::O_WRONLY | OpenFlags::O_RDWR)
47+ // {
48+ Ok ( handle. write ( buffer) ?)
49+ // } else {
50+ // Err(SyscallError::EACCES)
51+ // }
5052}
5153
5254#[ syscall]
@@ -528,25 +530,8 @@ pub fn link(src_path: &Path, dest_path: &Path) -> Result<usize, SyscallError> {
528530 Ok ( 0 )
529531}
530532
531- #[ syscall]
532- pub fn poll (
533- fds : & mut [ PollFd ] ,
534- // TODO: Use the provided timeout.
535- _timeout : & TimeSpec ,
536- sigmask : usize ,
537- ) -> Result < usize , SyscallError > {
538- if fds. len ( ) == 0 {
539- // nothing to do.
540- return Ok ( 0x00 ) ;
541- }
542-
533+ fn do_poll ( fds : & mut [ PollFd ] , timeout : Option < & TimeSpec > ) -> Result < usize , SyscallError > {
543534 let current_task = scheduler:: get_scheduler ( ) . current_task ( ) ;
544- let signals = current_task. signals ( ) ;
545-
546- let mut old_mask = 0 ;
547-
548- // Update the signal mask.
549- signals. set_mask ( SigProcMask :: Set , Some ( sigmask as u64 ) , Some ( & mut old_mask) ) ;
550535
551536 let mut poll_table = PollTable :: default ( ) ;
552537 let mut n = 0 ;
@@ -570,7 +555,7 @@ pub fn poll(
570555
571556 let ready: PollEventFlags = handle. inode ( ) . poll ( None ) ?. into ( ) ;
572557
573- if ready . contains ( fd. events ) {
558+ if ! ( ready & fd. events ) . is_empty ( ) {
574559 // The registered event is ready; increment the number of ready events
575560 // and update revents mask for this event.
576561 fd. revents = ready & fd. events ;
@@ -589,6 +574,56 @@ pub fn poll(
589574 return Ok ( n) ;
590575 }
591576
577+ // Start the timer if timeout specified, if not, we can block indefinitely.
578+ if let Some ( timeout) = timeout {
579+ // If the timeout is zero, then we have to return without blocking.
580+ if timeout. tv_nsec == 0 && timeout. tv_sec == 0 {
581+ return Ok ( 0 ) ;
582+ }
583+ }
584+
585+ crate :: unwind:: unwind_stack_trace ( ) ;
586+
587+ ' search: loop {
588+ // Wait till one of the file descriptor to be ready.
589+ scheduler:: get_scheduler ( ) . inner . await_io ( ) ?;
590+
591+ for ( handle, index) in refds. iter ( ) {
592+ let pollfd = & mut fds[ * index] ;
593+ let ready: PollEventFlags = handle. inode ( ) . poll ( None ) ?. into ( ) ;
594+
595+ if !( ready & pollfd. events ) . is_empty ( ) {
596+ pollfd. revents = ready & pollfd. events ;
597+ break ' search Ok ( 1 ) ;
598+ }
599+ }
600+ }
601+ }
602+
603+ #[ syscall]
604+ pub fn poll ( fds : & mut [ PollFd ] , timeout : usize , sigmask : usize ) -> Result < usize , SyscallError > {
605+ // Nothing to poll on.
606+ if fds. len ( ) == 0 {
607+ return Ok ( 0 ) ;
608+ }
609+
610+ // The timeout can be NULL.
611+ let timeout = if timeout != 0x00 {
612+ Some ( crate :: utils:: validate_ptr ( timeout as * const TimeSpec ) . ok_or ( SyscallError :: EINVAL ) ?)
613+ } else {
614+ None
615+ } ;
616+
617+ let current_task = scheduler:: get_scheduler ( ) . current_task ( ) ;
618+ let signals = current_task. signals ( ) ;
619+
620+ let mut old_mask = 0 ;
621+
622+ // Update the signal mask.
623+ signals. set_mask ( SigProcMask :: Set , Some ( sigmask as u64 ) , Some ( & mut old_mask) ) ;
624+
625+ let n = do_poll ( fds, timeout) ?;
626+
592627 // Restore the orignal signal mask.
593628 signals. set_mask ( SigProcMask :: Set , Some ( old_mask) , None ) ;
594629 Ok ( n)
0 commit comments