@@ -189,7 +189,7 @@ struct peer {
189189 bool degraded ;
190190 struct {
191191 uint64_t delay ;
192- sd_event_source * source ;
192+ uint64_t deadline ;
193193 int npolls ;
194194 mctp_eid_t eid ;
195195 uint8_t endpoint_type ;
@@ -248,6 +248,10 @@ struct ctx {
248248
249249 // maximum pool size for assumed MCTP Bridge
250250 uint8_t max_pool_size ;
251+
252+ uint64_t now ;
253+ uint64_t next_deadline ;
254+ int timerfd ;
251255};
252256
253257static int emit_endpoint_added (const struct peer * peer );
@@ -1791,6 +1795,7 @@ static int add_peer(struct ctx *ctx, const dest_phys *dest, mctp_eid_t eid,
17911795 memcpy (& peer -> phys , dest , sizeof (* dest ));
17921796 peer -> state = REMOTE ;
17931797 peer -> ctx = ctx ;
1798+ peer -> recovery .deadline = UINT64_MAX ;
17941799
17951800 // Update network eid map
17961801 n -> peers [eid ] = peer ;
@@ -1851,16 +1856,7 @@ static int remove_peer(struct peer *peer)
18511856
18521857 // Clear it
18531858 if (peer -> degraded ) {
1854- int rc ;
1855-
1856- rc = sd_event_source_set_enabled (peer -> recovery .source ,
1857- SD_EVENT_OFF );
1858- if (rc < 0 ) {
1859- /* XXX: Fix caller assumptions? */
1860- warnx ("Failed to stop recovery timer while removing peer: %d" ,
1861- rc );
1862- }
1863- sd_event_source_unref (peer -> recovery .source );
1859+ peer -> recovery .deadline = UINT64_MAX ;
18641860 }
18651861
18661862 n -> peers [peer -> eid ] = NULL ;
@@ -3079,10 +3075,19 @@ static int method_endpoint_remove(sd_bus_message *call, void *data,
30793075 (MCTP_I2C_TSYM_MT1_MAX_US + 2 * MCTP_I2C_TSYM_MT3_MAX_US)
30803076#define MCTP_I2C_TSYM_MT2_MAX_MS MCTP_I2C_TSYM_MT4_MIN_US
30813077
3082- static int peer_endpoint_recover (sd_event_source * s , uint64_t usec ,
3083- void * userdata )
3078+ static int update_deadline (struct ctx * ctx , uint64_t new_deadline )
3079+ {
3080+ uint64_t prev_deadline ;
3081+
3082+ if (ctx -> next_deadline < new_deadline )
3083+ return 0 ;
3084+
3085+ return mctp_ops .timerfd .settime (ctx -> timerfd , new_deadline ,
3086+ & prev_deadline );
3087+ }
3088+
3089+ static int peer_endpoint_recover (struct peer * peer )
30843090{
3085- struct peer * peer = userdata ;
30863091 struct ctx * ctx = peer -> ctx ;
30873092 const char * peer_path ;
30883093 int rc ;
@@ -3145,8 +3150,7 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
31453150 /* It's not known to be the same device, allocate a new EID */
31463151 dest_phys phys = peer -> phys ;
31473152
3148- assert (sd_event_source_get_enabled (
3149- peer -> recovery .source , NULL ) == 0 );
3153+ peer -> recovery .deadline = UINT64_MAX ;
31503154 remove_peer (peer );
31513155 /*
31523156 * The representation of the old peer is now gone. Set up the new peer,
@@ -3184,28 +3188,21 @@ static int peer_endpoint_recover(sd_event_source *s, uint64_t usec,
31843188 goto reschedule ;
31853189 }
31863190
3187- assert (sd_event_source_get_enabled (peer -> recovery .source , NULL ) == 0 );
3188- sd_event_source_unref (peer -> recovery .source );
31893191 peer -> recovery .delay = 0 ;
3190- peer -> recovery .source = NULL ;
3192+ peer -> recovery .deadline = UINT64_MAX ;
31913193 peer -> recovery .npolls = 0 ;
31923194
31933195 return rc ;
31943196
31953197reschedule :
31963198 if (peer -> recovery .npolls > 0 ) {
3197- rc = sd_event_source_set_time_relative (peer -> recovery .source ,
3198- peer -> recovery .delay );
3199- if (rc >= 0 ) {
3200- rc = sd_event_source_set_enabled (peer -> recovery .source ,
3201- SD_EVENT_ONESHOT );
3202- }
3199+ peer -> recovery .deadline = ctx -> now + peer -> recovery .delay ;
3200+ rc = update_deadline (ctx , peer -> recovery .deadline );
32033201 }
32043202 if (rc < 0 ) {
32053203reclaim :
32063204 /* Recovery unsuccessful, clean up the peer */
3207- assert (sd_event_source_get_enabled (peer -> recovery .source ,
3208- NULL ) == 0 );
3205+ peer -> recovery .deadline = UINT64_MAX ;
32093206 remove_peer (peer );
32103207 }
32113208 return rc < 0 ? rc : 0 ;
@@ -3225,18 +3222,13 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32253222
32263223 if (!previously ) {
32273224 assert (!peer -> recovery .delay );
3228- assert (! peer -> recovery .source );
3225+ assert (peer -> recovery .deadline == UINT64_MAX );
32293226 assert (!peer -> recovery .npolls );
32303227 peer -> recovery .npolls = MCTP_I2C_TSYM_MN1_MIN + 1 ;
32313228 peer -> recovery .delay =
32323229 (MCTP_I2C_TSYM_TRECLAIM_MIN_US / 2 ) - ctx -> mctp_timeout ;
3233- rc = sd_event_add_time_relative (
3234- ctx -> event , & peer -> recovery .source , CLOCK_MONOTONIC , 0 ,
3235- ctx -> mctp_timeout , peer_endpoint_recover , peer );
3236- if (rc < 0 ) {
3237- goto out ;
3238- }
3239-
3230+ peer -> recovery .deadline = ctx -> now + ctx -> mctp_timeout ;
3231+ update_deadline (ctx , peer -> recovery .deadline );
32403232 peer -> degraded = true;
32413233
32423234 rc = sd_bus_emit_properties_changed (
@@ -3255,13 +3247,10 @@ static int method_endpoint_recover(sd_bus_message *call, void *data,
32553247 if (rc < 0 && !previously ) {
32563248 if (peer -> degraded ) {
32573249 /* Cleanup the timer if it was setup successfully. */
3258- sd_event_source_set_enabled (peer -> recovery .source ,
3259- SD_EVENT_OFF );
3260- sd_event_source_unref (peer -> recovery .source );
3250+ peer -> recovery .deadline = UINT64_MAX ;
32613251 }
32623252 peer -> degraded = previously ;
32633253 peer -> recovery .delay = 0 ;
3264- peer -> recovery .source = NULL ;
32653254 peer -> recovery .npolls = 0 ;
32663255 }
32673256 set_berr (ctx , rc , berr );
@@ -4949,6 +4938,52 @@ static int endpoint_allocate_eids(struct peer *peer)
49494938 return 0 ;
49504939}
49514940
4941+ int global_time_callback (sd_event_source * source , int timerfd , uint revents ,
4942+ void * userdata )
4943+ {
4944+ struct ctx * ctx = userdata ;
4945+ uint64_t n_expireds ;
4946+ size_t i ;
4947+
4948+ mctp_ops .timerfd .read (timerfd , & n_expireds );
4949+ mctp_ops .timerfd .gettime (timerfd , & ctx -> now );
4950+
4951+ for (i = 0 ; i < ctx -> num_peers ; i ++ ) {
4952+ struct peer * p = ctx -> peers [i ];
4953+ if (p -> recovery .deadline <= ctx -> now ) {
4954+ peer_endpoint_recover (p );
4955+ }
4956+ }
4957+
4958+ return 0 ;
4959+ }
4960+
4961+ int setup_timers (struct ctx * ctx )
4962+ {
4963+ int rc ;
4964+
4965+ ctx -> timerfd = mctp_ops .timerfd .create ();
4966+ if (ctx -> timerfd < 0 ) {
4967+ warn ("timerfd_create" );
4968+ return - errno ;
4969+ }
4970+
4971+ rc = mctp_ops .timerfd .gettime (ctx -> timerfd , & ctx -> now );
4972+ if (rc < 0 ) {
4973+ warn ("timerfd_gettime" );
4974+ return - errno ;
4975+ }
4976+
4977+ ctx -> next_deadline = UINT64_MAX ;
4978+
4979+ rc = sd_event_add_io (ctx -> event , NULL , ctx -> timerfd , EPOLLIN ,
4980+ global_time_callback , ctx );
4981+ if (rc < 0 )
4982+ return rc ;
4983+
4984+ return 0 ;
4985+ }
4986+
49524987int main (int argc , char * * argv )
49534988{
49544989 struct ctx ctxi = { 0 }, * ctx = & ctxi ;
@@ -4997,6 +5032,10 @@ int main(int argc, char **argv)
49975032 if (rc < 0 )
49985033 return 1 ;
49995034
5035+ rc = setup_timers (ctx );
5036+ if (rc < 0 )
5037+ return 1 ;
5038+
50005039 // TODO add net argument?
50015040 rc = listen_control_msg (ctx , MCTP_NET_ANY );
50025041 if (rc < 0 ) {
0 commit comments