@@ -4,6 +4,7 @@ use std::io;
44use std:: rc:: { Rc , Weak } ;
55use std:: time:: Duration ;
66
7+ use crate :: concurrency:: VClock ;
78use crate :: shims:: unix:: fd:: { FdId , FileDescriptionRef , WeakFileDescriptionRef } ;
89use crate :: shims:: unix:: * ;
910use crate :: * ;
@@ -19,7 +20,7 @@ struct Epoll {
1920 /// and file descriptor value.
2021 // This is an Rc because EpollInterest need to hold a reference to update
2122 // it.
22- ready_list : Rc < RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > > ,
23+ ready_list : Rc < ReadyList > ,
2324 /// A list of thread ids blocked on this epoll instance.
2425 thread_id : RefCell < Vec < ThreadId > > ,
2526}
@@ -63,7 +64,7 @@ pub struct EpollEventInterest {
6364 /// <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>
6465 data : u64 ,
6566 /// Ready list of the epoll instance under which this EpollEventInterest is registered.
66- ready_list : Rc < RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > > ,
67+ ready_list : Rc < ReadyList > ,
6768 /// The epoll file description that this EpollEventInterest is registered under.
6869 weak_epfd : WeakFileDescriptionRef ,
6970}
@@ -88,6 +89,12 @@ pub struct EpollReadyEvents {
8889 pub epollerr : bool ,
8990}
9091
92+ #[ derive( Debug , Default ) ]
93+ struct ReadyList {
94+ mapping : RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > ,
95+ clock : RefCell < VClock > ,
96+ }
97+
9198impl EpollReadyEvents {
9299 pub fn new ( ) -> Self {
93100 EpollReadyEvents {
@@ -127,7 +134,7 @@ impl EpollReadyEvents {
127134}
128135
129136impl Epoll {
130- fn get_ready_list ( & self ) -> Rc < RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > > {
137+ fn get_ready_list ( & self ) -> Rc < ReadyList > {
131138 Rc :: clone ( & self . ready_list )
132139 }
133140}
@@ -207,9 +214,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
207214 ) ;
208215 }
209216
210- let mut epoll_instance = Epoll :: default ( ) ;
211- epoll_instance. ready_list = Rc :: new ( RefCell :: new ( BTreeMap :: new ( ) ) ) ;
212-
213217 let fd = this. machine . fds . insert_new ( Epoll :: default ( ) ) ;
214218 Ok ( Scalar :: from_i32 ( fd) )
215219 }
@@ -377,7 +381,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
377381 drop ( epoll_interest) ;
378382
379383 // Remove related epoll_interest from ready list.
380- ready_list. borrow_mut ( ) . remove ( & epoll_key) ;
384+ ready_list. mapping . borrow_mut ( ) . remove ( & epoll_key) ;
381385
382386 // Remove dangling EpollEventInterest from its global table.
383387 // .unwrap() below should succeed because the file description id must have registered
@@ -471,8 +475,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
471475 let epoll_file_description = epfd
472476 . downcast :: < Epoll > ( )
473477 . ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_wait`" ) ) ?;
474- let binding = epoll_file_description. get_ready_list ( ) ;
475- ready_list_empty = binding. borrow_mut ( ) . is_empty ( ) ;
478+ ready_list_empty = epoll_file_description. ready_list . mapping . borrow ( ) . is_empty ( ) ;
476479 thread_ids = epoll_file_description. thread_id . borrow_mut ( ) ;
477480 }
478481 if timeout == 0 || !ready_list_empty {
@@ -561,9 +564,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
561564 // holds a strong ref to epoll_interest.
562565 let epfd = epoll_interest. borrow ( ) . weak_epfd . upgrade ( ) . unwrap ( ) ;
563566 // FIXME: We can randomly pick a thread to unblock.
564- if let Some ( thread_id) =
565- epfd. downcast :: < Epoll > ( ) . unwrap ( ) . thread_id . borrow_mut ( ) . pop ( )
566- {
567+
568+ let epoll = epfd. downcast :: < Epoll > ( ) . unwrap ( ) ;
569+
570+ // Synchronize running thread to the epoll ready list.
571+ if let Some ( clock) = & this. release_clock ( ) {
572+ epoll. ready_list . clock . borrow_mut ( ) . join ( clock) ;
573+ }
574+
575+ if let Some ( thread_id) = epoll. thread_id . borrow_mut ( ) . pop ( ) {
567576 waiter. push ( thread_id) ;
568577 } ;
569578 }
@@ -617,7 +626,7 @@ fn check_and_update_one_event_interest<'tcx>(
617626 // insert an epoll_return to the ready list.
618627 if flags != 0 {
619628 let epoll_key = ( id, epoll_event_interest. fd_num ) ;
620- let ready_list = & mut epoll_event_interest. ready_list . borrow_mut ( ) ;
629+ let ready_list = & mut epoll_event_interest. ready_list . mapping . borrow_mut ( ) ;
621630 let event_instance = EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
622631 // Triggers the notification by inserting it to the ready list.
623632 ready_list. insert ( epoll_key, event_instance) ;
@@ -644,7 +653,11 @@ fn blocking_epoll_callback<'tcx>(
644653 . ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_wait`" ) ) ?;
645654
646655 let ready_list = epoll_file_description. get_ready_list ( ) ;
647- let mut ready_list = ready_list. borrow_mut ( ) ;
656+
657+ // Synchronize waking thread from the epoll ready list.
658+ ecx. acquire_clock ( & ready_list. clock . borrow ( ) ) ;
659+
660+ let mut ready_list = ready_list. mapping . borrow_mut ( ) ;
648661 let mut num_of_events: i32 = 0 ;
649662 let mut array_iter = ecx. project_array_fields ( events) ?;
650663
0 commit comments