@@ -269,10 +269,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
269
269
let mut interest_list = epoll_file_description. interest_list . borrow_mut ( ) ;
270
270
let ready_list = & epoll_file_description. ready_list ;
271
271
272
- let Some ( file_descriptor ) = this. machine . fds . get ( fd) else {
272
+ let Some ( fd_ref ) = this. machine . fds . get ( fd) else {
273
273
return Ok ( Scalar :: from_i32 ( this. fd_not_found ( ) ?) ) ;
274
274
} ;
275
- let id = file_descriptor . get_id ( ) ;
275
+ let id = fd_ref . get_id ( ) ;
276
276
277
277
if op == epoll_ctl_add || op == epoll_ctl_mod {
278
278
// Read event bitmask and data from epoll_event passed by caller.
@@ -332,7 +332,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
332
332
}
333
333
}
334
334
335
- let id = file_descriptor. get_id ( ) ;
336
335
// Create an epoll_interest.
337
336
let interest = Rc :: new ( RefCell :: new ( EpollEventInterest {
338
337
file_descriptor : fd,
@@ -344,7 +343,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
344
343
if op == epoll_ctl_add {
345
344
// Insert an epoll_interest to global epoll_interest list.
346
345
this. machine . epoll_interests . insert_epoll_interest ( id, Rc :: downgrade ( & interest) ) ;
347
- interest_list. insert ( epoll_key, interest) ;
346
+ interest_list. insert ( epoll_key, Rc :: clone ( & interest) ) ;
348
347
} else {
349
348
// Directly modify the epoll_interest so the global epoll_event_interest table
350
349
// will be updated too.
@@ -353,9 +352,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
353
352
epoll_interest. data = data;
354
353
}
355
354
356
- // Readiness will be updated immediately when the epoll_event_interest is added or modified.
357
- this . check_and_update_readiness ( & file_descriptor ) ? ;
358
-
355
+ // Notification will be returned for current epfd if there is event in the file
356
+ // descriptor we registered.
357
+ check_and_update_one_event_interest ( & fd_ref , interest , id , this ) ? ;
359
358
return Ok ( Scalar :: from_i32 ( 0 ) ) ;
360
359
} else if op == epoll_ctl_del {
361
360
let epoll_key = ( id, fd) ;
@@ -489,25 +488,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
489
488
let id = fd_ref. get_id ( ) ;
490
489
// Get a list of EpollEventInterest that is associated to a specific file description.
491
490
if let Some ( epoll_interests) = this. machine . epoll_interests . get_epoll_interest ( id) {
492
- let epoll_ready_events = fd_ref. get_epoll_ready_events ( ) ?;
493
- // Get the bitmask of ready events.
494
- let ready_events = epoll_ready_events. get_event_bitmask ( this) ;
495
-
496
491
for weak_epoll_interest in epoll_interests {
497
492
if let Some ( epoll_interest) = weak_epoll_interest. upgrade ( ) {
498
- // This checks if any of the events specified in epoll_event_interest.events
499
- // match those in ready_events.
500
- let epoll_event_interest = epoll_interest. borrow ( ) ;
501
- let flags = epoll_event_interest. events & ready_events;
502
- // If there is any event that we are interested in being specified as ready,
503
- // insert an epoll_return to the ready list.
504
- if flags != 0 {
505
- let epoll_key = ( id, epoll_event_interest. file_descriptor ) ;
506
- let ready_list = & mut epoll_event_interest. ready_list . borrow_mut ( ) ;
507
- let event_instance =
508
- EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
509
- ready_list. insert ( epoll_key, event_instance) ;
510
- }
493
+ check_and_update_one_event_interest ( fd_ref, epoll_interest, id, this) ?;
511
494
}
512
495
}
513
496
}
@@ -532,3 +515,30 @@ fn ready_list_next(
532
515
}
533
516
return None ;
534
517
}
518
+
519
+ /// This helper function checks whether an epoll notification should be triggered for a specific
520
+ /// epoll_interest and, if necessary, triggers the notification. Unlike check_and_update_readiness,
521
+ /// this function sends a notification to only one epoll instance.
522
+ fn check_and_update_one_event_interest < ' tcx > (
523
+ fd_ref : & FileDescriptionRef ,
524
+ interest : Rc < RefCell < EpollEventInterest > > ,
525
+ id : FdId ,
526
+ ecx : & MiriInterpCx < ' tcx > ,
527
+ ) -> InterpResult < ' tcx > {
528
+ // Get the bitmask of ready events for a file description.
529
+ let ready_events_bitmask = fd_ref. get_epoll_ready_events ( ) ?. get_event_bitmask ( ecx) ;
530
+ let epoll_event_interest = interest. borrow ( ) ;
531
+ // This checks if any of the events specified in epoll_event_interest.events
532
+ // match those in ready_events.
533
+ let flags = epoll_event_interest. events & ready_events_bitmask;
534
+ // If there is any event that we are interested in being specified as ready,
535
+ // insert an epoll_return to the ready list.
536
+ if flags != 0 {
537
+ let epoll_key = ( id, epoll_event_interest. file_descriptor ) ;
538
+ let ready_list = & mut epoll_event_interest. ready_list . borrow_mut ( ) ;
539
+ let event_instance = EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
540
+ // Triggers the notification by inserting it to the ready list.
541
+ ready_list. insert ( epoll_key, event_instance) ;
542
+ }
543
+ Ok ( ( ) )
544
+ }
0 commit comments