@@ -478,9 +478,11 @@ static int cb_exit_loop_io(sd_event_source *s, int fd, uint32_t revents,
478478 return 0 ;
479479}
480480
481- static int cb_exit_loop_timeout (sd_event_source * s , uint64_t usec ,
481+ static int cb_exit_loop_timeout (sd_event_source * s , int timerfd , uint revents ,
482482 void * userdata )
483483{
484+ // flush the timerfd
485+ mctp_ops .timerfd .read (timerfd , NULL );
484486 sd_event_exit (sd_event_source_get_event (s ), - ETIMEDOUT );
485487 return 0 ;
486488}
@@ -490,15 +492,28 @@ static int cb_exit_loop_timeout(sd_event_source *s, uint64_t usec,
490492static int wait_fd_timeout (int fd , short events , uint64_t timeout_usec )
491493{
492494 int rc ;
495+ int timerfd = -1 ;
493496 sd_event * ev = NULL ;
494497
495498 // Create a new event loop just for the event+timeout
496499 rc = sd_event_new (& ev );
497500 if (rc < 0 )
498501 goto out ;
499502
500- rc = sd_event_add_time_relative (ev , NULL , CLOCK_MONOTONIC , timeout_usec ,
501- 0 , cb_exit_loop_timeout , NULL );
503+ timerfd = mctp_ops .timerfd .create ();
504+ if (timerfd < 0 ) {
505+ rc = - errno ;
506+ goto out ;
507+ }
508+
509+ rc = mctp_ops .timerfd .settime (timerfd , timeout_usec , NULL );
510+ if (rc < 0 ) {
511+ rc = - errno ;
512+ goto out ;
513+ }
514+
515+ rc = sd_event_add_io (ev , NULL , timerfd , EPOLLIN , cb_exit_loop_timeout ,
516+ NULL );
502517 if (rc < 0 )
503518 goto out ;
504519
@@ -510,8 +525,8 @@ static int wait_fd_timeout(int fd, short events, uint64_t timeout_usec)
510525 rc = sd_event_loop (ev );
511526
512527out :
513- if (ev )
514- sd_event_unref ( ev );
528+ sd_event_unref (ev );
529+ close ( timerfd );
515530 return rc ;
516531}
517532
@@ -3115,7 +3130,7 @@ static int method_endpoint_remove(sd_bus_message *call, void *data,
31153130 (MCTP_I2C_TSYM_MT1_MAX_US + 2 * MCTP_I2C_TSYM_MT3_MAX_US)
31163131#define MCTP_I2C_TSYM_MT2_MAX_MS MCTP_I2C_TSYM_MT4_MIN_US
31173132
3118- static int peer_endpoint_recover (sd_event_source * s , uint64_t usec ,
3133+ static int peer_endpoint_recover (sd_event_source * s , int timerfd , uint revents ,
31193134 void * userdata )
31203135{
31213136 struct peer * peer = userdata ;
@@ -3135,6 +3150,12 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
31353150
31363151 peer -> recovery .npolls -- ;
31373152
3153+ // flush the timerfd
3154+ rc = mctp_ops .timerfd .read (timerfd , NULL );
3155+ if (rc < 0 ) {
3156+ goto reschedule ;
3157+ }
3158+
31383159 /*
31393160 * Test if we still have connectivity to the endpoint. If we do, we will get a
31403161 * response reporting the current EID. This is the test recommended by 8.17.6
@@ -3230,8 +3251,8 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
32303251
32313252reschedule :
32323253 if (peer -> recovery .npolls > 0 ) {
3233- rc = sd_event_source_set_time_relative ( peer -> recovery .source ,
3234- peer -> recovery . delay );
3254+ rc = mctp_ops . timerfd . settime ( timerfd , peer -> recovery .delay ,
3255+ NULL );
32353256 if (rc >= 0 ) {
32363257 rc = sd_event_source_set_enabled (peer -> recovery .source ,
32373258 SD_EVENT_ONESHOT );
@@ -3253,11 +3274,13 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32533274 struct peer * peer ;
32543275 bool previously ;
32553276 struct ctx * ctx ;
3277+ int timerfd ;
32563278 int rc ;
32573279
32583280 peer = data ;
32593281 ctx = peer -> ctx ;
32603282 previously = peer -> degraded ;
3283+ timerfd = -1 ;
32613284
32623285 if (!previously ) {
32633286 assert (!peer -> recovery .delay );
@@ -3266,13 +3289,39 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32663289 peer -> recovery .npolls = MCTP_I2C_TSYM_MN1_MIN + 1 ;
32673290 peer -> recovery .delay =
32683291 (MCTP_I2C_TSYM_TRECLAIM_MIN_US / 2 ) - ctx -> mctp_timeout ;
3269- rc = sd_event_add_time_relative (
3270- ctx -> event , & peer -> recovery .source , CLOCK_MONOTONIC , 0 ,
3271- ctx -> mctp_timeout , peer_endpoint_recover , peer );
3292+
3293+ timerfd = mctp_ops .timerfd .create ();
3294+ if (timerfd < 0 ) {
3295+ rc = - errno ;
3296+ goto out ;
3297+ }
3298+
3299+ rc = mctp_ops .timerfd .settime (timerfd , ctx -> mctp_timeout , NULL );
3300+ if (rc < 0 ) {
3301+ rc = - errno ;
3302+ goto out ;
3303+ }
3304+
3305+ rc = sd_event_add_io (ctx -> event , & peer -> recovery .source ,
3306+ timerfd , EPOLLIN , peer_endpoint_recover ,
3307+ peer );
32723308 if (rc < 0 ) {
32733309 goto out ;
32743310 }
32753311
3312+ rc = sd_event_source_set_enabled (peer -> recovery .source ,
3313+ SD_EVENT_ONESHOT );
3314+ if (rc < 0 ) {
3315+ goto out ;
3316+ }
3317+
3318+ rc = sd_event_source_set_io_fd_own (peer -> recovery .source , true);
3319+ if (rc < 0 ) {
3320+ goto out ;
3321+ }
3322+ // prevent double close, now that sd_event_source own the fd
3323+ timerfd = -1 ;
3324+
32763325 peer -> degraded = true;
32773326
32783327 rc = sd_bus_emit_properties_changed (
@@ -3289,12 +3338,8 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32893338
32903339out :
32913340 if (rc < 0 && !previously ) {
3292- if (peer -> degraded ) {
3293- /* Cleanup the timer if it was setup successfully. */
3294- sd_event_source_set_enabled (peer -> recovery .source ,
3295- SD_EVENT_OFF );
3296- sd_event_source_unref (peer -> recovery .source );
3297- }
3341+ sd_event_source_disable_unref (peer -> recovery .source );
3342+ close (timerfd );
32983343 peer -> degraded = previously ;
32993344 peer -> recovery .delay = 0 ;
33003345 peer -> recovery .source = NULL ;
0 commit comments