@@ -4,6 +4,7 @@ use std::io;
4
4
use std:: rc:: { Rc , Weak } ;
5
5
use std:: time:: Duration ;
6
6
7
+ use crate :: concurrency:: VClock ;
7
8
use crate :: shims:: unix:: fd:: { FdId , FileDescriptionRef , WeakFileDescriptionRef } ;
8
9
use crate :: shims:: unix:: * ;
9
10
use crate :: * ;
@@ -19,7 +20,7 @@ struct Epoll {
19
20
/// and file descriptor value.
20
21
// This is an Rc because EpollInterest need to hold a reference to update
21
22
// it.
22
- ready_list : Rc < RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > > ,
23
+ ready_list : Rc < ReadyList > ,
23
24
/// A list of thread ids blocked on this epoll instance.
24
25
thread_id : RefCell < Vec < ThreadId > > ,
25
26
}
@@ -63,7 +64,7 @@ pub struct EpollEventInterest {
63
64
/// <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>
64
65
data : u64 ,
65
66
/// 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 > ,
67
68
/// The epoll file description that this EpollEventInterest is registered under.
68
69
weak_epfd : WeakFileDescriptionRef ,
69
70
}
@@ -88,6 +89,12 @@ pub struct EpollReadyEvents {
88
89
pub epollerr : bool ,
89
90
}
90
91
92
+ #[ derive( Debug , Default ) ]
93
+ struct ReadyList {
94
+ mapping : RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > ,
95
+ clock : RefCell < VClock > ,
96
+ }
97
+
91
98
impl EpollReadyEvents {
92
99
pub fn new ( ) -> Self {
93
100
EpollReadyEvents {
@@ -127,7 +134,7 @@ impl EpollReadyEvents {
127
134
}
128
135
129
136
impl Epoll {
130
- fn get_ready_list ( & self ) -> Rc < RefCell < BTreeMap < ( FdId , i32 ) , EpollEventInstance > > > {
137
+ fn get_ready_list ( & self ) -> Rc < ReadyList > {
131
138
Rc :: clone ( & self . ready_list )
132
139
}
133
140
}
@@ -207,9 +214,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
207
214
) ;
208
215
}
209
216
210
- let mut epoll_instance = Epoll :: default ( ) ;
211
- epoll_instance. ready_list = Rc :: new ( RefCell :: new ( BTreeMap :: new ( ) ) ) ;
212
-
213
217
let fd = this. machine . fds . insert_new ( Epoll :: default ( ) ) ;
214
218
Ok ( Scalar :: from_i32 ( fd) )
215
219
}
@@ -377,7 +381,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
377
381
drop ( epoll_interest) ;
378
382
379
383
// Remove related epoll_interest from ready list.
380
- ready_list. borrow_mut ( ) . remove ( & epoll_key) ;
384
+ ready_list. mapping . borrow_mut ( ) . remove ( & epoll_key) ;
381
385
382
386
// Remove dangling EpollEventInterest from its global table.
383
387
// .unwrap() below should succeed because the file description id must have registered
@@ -471,8 +475,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
471
475
let epoll_file_description = epfd
472
476
. downcast :: < Epoll > ( )
473
477
. 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 ( ) ;
476
479
thread_ids = epoll_file_description. thread_id . borrow_mut ( ) ;
477
480
}
478
481
if timeout == 0 || !ready_list_empty {
@@ -561,9 +564,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
561
564
// holds a strong ref to epoll_interest.
562
565
let epfd = epoll_interest. borrow ( ) . weak_epfd . upgrade ( ) . unwrap ( ) ;
563
566
// 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 ( ) {
567
576
waiter. push ( thread_id) ;
568
577
} ;
569
578
}
@@ -617,7 +626,7 @@ fn check_and_update_one_event_interest<'tcx>(
617
626
// insert an epoll_return to the ready list.
618
627
if flags != 0 {
619
628
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 ( ) ;
621
630
let event_instance = EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
622
631
// Triggers the notification by inserting it to the ready list.
623
632
ready_list. insert ( epoll_key, event_instance) ;
@@ -644,7 +653,11 @@ fn blocking_epoll_callback<'tcx>(
644
653
. ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_wait`" ) ) ?;
645
654
646
655
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 ( ) ;
648
661
let mut num_of_events: i32 = 0 ;
649
662
let mut array_iter = ecx. project_array_fields ( events) ?;
650
663
0 commit comments