@@ -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
}
@@ -374,7 +381,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
374
381
drop ( epoll_interest) ;
375
382
376
383
// Remove related epoll_interest from ready list.
377
- ready_list. borrow_mut ( ) . remove ( & epoll_key) ;
384
+ ready_list. mapping . borrow_mut ( ) . remove ( & epoll_key) ;
378
385
379
386
// Remove dangling EpollEventInterest from its global table.
380
387
// .unwrap() below should succeed because the file description id must have registered
@@ -469,7 +476,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
469
476
. downcast :: < Epoll > ( )
470
477
. ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_wait`" ) ) ?;
471
478
let binding = epoll_file_description. get_ready_list ( ) ;
472
- ready_list_empty = binding. borrow_mut ( ) . is_empty ( ) ;
479
+ ready_list_empty = binding. mapping . borrow_mut ( ) . is_empty ( ) ;
473
480
thread_ids = epoll_file_description. thread_id . borrow_mut ( ) ;
474
481
}
475
482
if timeout == 0 || !ready_list_empty {
@@ -558,9 +565,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
558
565
// holds a strong ref to epoll_interest.
559
566
let epfd = epoll_interest. borrow ( ) . weak_epfd . upgrade ( ) . unwrap ( ) ;
560
567
// FIXME: We can randomly pick a thread to unblock.
561
- if let Some ( thread_id) =
562
- epfd. downcast :: < Epoll > ( ) . unwrap ( ) . thread_id . borrow_mut ( ) . pop ( )
563
- {
568
+
569
+ let epoll = epfd. downcast :: < Epoll > ( ) . unwrap ( ) ;
570
+
571
+ // Synchronize running thread to the epoll ready list.
572
+ if let Some ( clock) = & this. release_clock ( ) {
573
+ epoll. ready_list . clock . borrow_mut ( ) . join ( clock) ;
574
+ }
575
+
576
+ if let Some ( thread_id) = epoll. thread_id . borrow_mut ( ) . pop ( ) {
564
577
waiter. push ( thread_id) ;
565
578
} ;
566
579
}
@@ -614,7 +627,7 @@ fn check_and_update_one_event_interest<'tcx>(
614
627
// insert an epoll_return to the ready list.
615
628
if flags != 0 {
616
629
let epoll_key = ( id, epoll_event_interest. fd_num ) ;
617
- let ready_list = & mut epoll_event_interest. ready_list . borrow_mut ( ) ;
630
+ let ready_list = & mut epoll_event_interest. ready_list . mapping . borrow_mut ( ) ;
618
631
let event_instance = EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
619
632
// Triggers the notification by inserting it to the ready list.
620
633
ready_list. insert ( epoll_key, event_instance) ;
@@ -641,7 +654,11 @@ fn blocking_epoll_callback<'tcx>(
641
654
. ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_wait`" ) ) ?;
642
655
643
656
let ready_list = epoll_file_description. get_ready_list ( ) ;
644
- let mut ready_list = ready_list. borrow_mut ( ) ;
657
+
658
+ // Synchronize waking thread from the epoll ready list.
659
+ ecx. acquire_clock ( & ready_list. clock . borrow ( ) ) ;
660
+
661
+ let mut ready_list = ready_list. mapping . borrow_mut ( ) ;
645
662
let mut num_of_events: i32 = 0 ;
646
663
let mut array_iter = ecx. project_array_fields ( events) ?;
647
664
0 commit comments