@@ -269,10 +269,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
269269 let mut interest_list = epoll_file_description. interest_list . borrow_mut ( ) ;
270270 let ready_list = & epoll_file_description. ready_list ;
271271
272- let Some ( file_descriptor ) = this. machine . fds . get ( fd) else {
272+ let Some ( fd_ref ) = this. machine . fds . get ( fd) else {
273273 return Ok ( Scalar :: from_i32 ( this. fd_not_found ( ) ?) ) ;
274274 } ;
275- let id = file_descriptor . get_id ( ) ;
275+ let id = fd_ref . get_id ( ) ;
276276
277277 if op == epoll_ctl_add || op == epoll_ctl_mod {
278278 // Read event bitmask and data from epoll_event passed by caller.
@@ -332,7 +332,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
332332 }
333333 }
334334
335- let id = file_descriptor. get_id ( ) ;
336335 // Create an epoll_interest.
337336 let interest = Rc :: new ( RefCell :: new ( EpollEventInterest {
338337 file_descriptor : fd,
@@ -344,7 +343,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
344343 if op == epoll_ctl_add {
345344 // Insert an epoll_interest to global epoll_interest list.
346345 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) ) ;
348347 } else {
349348 // Directly modify the epoll_interest so the global epoll_event_interest table
350349 // will be updated too.
@@ -353,9 +352,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
353352 epoll_interest. data = data;
354353 }
355354
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 ) ? ;
359358 return Ok ( Scalar :: from_i32 ( 0 ) ) ;
360359 } else if op == epoll_ctl_del {
361360 let epoll_key = ( id, fd) ;
@@ -489,25 +488,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
489488 let id = fd_ref. get_id ( ) ;
490489 // Get a list of EpollEventInterest that is associated to a specific file description.
491490 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-
496491 for weak_epoll_interest in epoll_interests {
497492 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) ?;
511494 }
512495 }
513496 }
@@ -532,3 +515,30 @@ fn ready_list_next(
532515 }
533516 return None ;
534517}
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