From 3a413bd8feb99a8e2be66f967f43b6216716e2bd Mon Sep 17 00:00:00 2001 From: Hans Heirman Date: Mon, 3 Jan 2022 14:42:24 +0100 Subject: [PATCH] Handle possible counter overflow cases in scheduler tick --- src/common/pf_scheduler.c | 31 ++++++++++++++++++++++++++----- src/pf_types.h | 1 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/common/pf_scheduler.c b/src/common/pf_scheduler.c index c4ffe718..09291108 100644 --- a/src/common/pf_scheduler.c +++ b/src/common/pf_scheduler.c @@ -273,6 +273,7 @@ void pf_scheduler_init (pnet_t * net, uint32_t tick_interval) net->scheduler_timeout_first = PF_MAX_TIMEOUTS; /* Nothing in queue */ net->scheduler_timeout_free = PF_MAX_TIMEOUTS; /* Nothing in queue. */ + net->scheduler_previous_time = os_get_current_time_us(); if (net->scheduler_timeout_mutex == NULL) { @@ -443,20 +444,40 @@ void pf_scheduler_remove (pnet_t * net, pf_scheduler_handle_t * handle) void pf_scheduler_tick (pnet_t * net) { uint32_t ix; + uint32_t when; pf_scheduler_timeout_ftn_t ftn; void * arg; uint32_t pf_current_time = os_get_current_time_us(); + uint32_t pf_previous_time = net->scheduler_previous_time; + net->scheduler_previous_time = pf_current_time; os_mutex_lock (net->scheduler_timeout_mutex); /* Send event to all expired delay entries. */ - while ((net->scheduler_timeout_first < PF_MAX_TIMEOUTS) && - ((int32_t) ( - pf_current_time - - net->scheduler_timeouts[net->scheduler_timeout_first].when) >= 0)) + while (net->scheduler_timeout_first < PF_MAX_TIMEOUTS) { - /* Unlink from busy list */ ix = net->scheduler_timeout_first; + when = net->scheduler_timeouts[ix].when; + + /* Exit loop if not yet expired */ + if (pf_current_time < when) { + if (pf_previous_time <= pf_current_time) { + /* Most common case; |--------PCW--------| */ + break; + } else if (pf_previous_time > when) { + /* Overflow of both current time and when; |CW----------------P| */ + break; + } + /* Else overflow of current time; |C-----------------PW| */ + } else if ( + pf_current_time > when && + pf_previous_time > when && + pf_previous_time <= pf_current_time) { + /* Overflow of when; |W-----------------PC| */ + break; + } + + /* Unlink from busy list */ pf_scheduler_unlink (net, &net->scheduler_timeout_first, ix); ftn = net->scheduler_timeouts[ix].cb; diff --git a/src/pf_types.h b/src/pf_types.h index f357edd5..7cabaf2c 100644 --- a/src/pf_types.h +++ b/src/pf_types.h @@ -2614,6 +2614,7 @@ struct pnet volatile uint32_t scheduler_timeout_free; os_mutex_t * scheduler_timeout_mutex; uint32_t scheduler_tick_interval; /* microseconds */ + uint32_t scheduler_previous_time; bool cmdev_initialized; pf_device_t cmdev_device; /* APIs and diag items */ pf_cmina_dcp_ase_t cmina_nonvolatile_dcp_ase; /* Reflects what is/should be