Merge pull request #13212 from Hyungsin/forupstream_xtimer_bug

sys/xtimer: compare two offsets rather than absolute times
This commit is contained in:
MichelRottleuthner 2020-01-30 10:15:41 +01:00 committed by GitHub
commit 2f418bf684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -43,7 +43,7 @@ static xtimer_t *timer_list_head = NULL;
static xtimer_t *long_list_head = NULL; static xtimer_t *long_list_head = NULL;
static bool _lltimer_ongoing = false; static bool _lltimer_ongoing = false;
static void _add_timer_to_list(xtimer_t **list_head, xtimer_t *timer); static void _add_timer_to_list(xtimer_t **list_head, xtimer_t *timer, uint32_t now);
static void _shoot(xtimer_t *timer); static void _shoot(xtimer_t *timer);
static inline void _update_short_timers(uint64_t *now); static inline void _update_short_timers(uint64_t *now);
static inline void _update_long_timers(uint64_t *now); static inline void _update_long_timers(uint64_t *now);
@ -93,7 +93,7 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
timer->long_start_time = (uint32_t)(now >> 32); timer->long_start_time = (uint32_t)(now >> 32);
if (!long_offset) { if (!long_offset) {
_add_timer_to_list(&timer_list_head, timer); _add_timer_to_list(&timer_list_head, timer, (uint32_t)now);
if (timer_list_head == timer) { if (timer_list_head == timer) {
DEBUG("_xtimer_set64(): timer is new list head. updating lltimer.\n"); DEBUG("_xtimer_set64(): timer is new list head. updating lltimer.\n");
@ -101,7 +101,7 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
} }
} }
else { else {
_add_timer_to_list(&long_list_head, timer); _add_timer_to_list(&long_list_head, timer, (uint32_t)now);
DEBUG("_xtimer_set64(): added longterm timer.\n"); DEBUG("_xtimer_set64(): added longterm timer.\n");
} }
irq_restore(state); irq_restore(state);
@ -148,27 +148,31 @@ static inline void _schedule_earliest_lltimer(uint32_t now)
/** /**
* @brief compare two timers. return true if timerA expires earlier than or equal to timerB and false otherwise. * @brief compare two timers. return true if timerA expires earlier than or equal to timerB and false otherwise.
*/ */
static bool _timer_comparison(xtimer_t* timerA, xtimer_t* timerB) static bool _timer_comparison(xtimer_t* timerA, xtimer_t* timerB, uint32_t now)
{ {
if (timerA->long_offset < timerB->long_offset) { if (timerA->long_offset < timerB->long_offset) {
return true; return true;
} }
if (timerA->long_offset == timerB->long_offset if (timerA->long_offset == timerB->long_offset) {
/* this condition is needed for when timerA was already expired before timerB starts */ uint32_t elapsedA = now - timerA->start_time;
&& (timerA->start_time + timerA->offset < timerB->start_time uint32_t elapsedB = now - timerB->start_time;
/* it is necessary to compare two offsets, instead of two absolute times */ /* it is necessary to compare two offsets, instead of two absolute times
|| timerA->start_time + timerA->offset - timerB->start_time <= timerB->offset)) { * two conditions: (1) timerA was already expired
* (2) timerA will expire earlier than or equal to timerB
*/
if (timerA->offset < elapsedA || timerA->offset - elapsedA <= timerB->offset - elapsedB) {
return true; return true;
} }
}
return false; return false;
} }
/** /**
* @brief add a timer to an ordered list of timers * @brief add a timer to an ordered list of timers
*/ */
static void _add_timer_to_list(xtimer_t **list_head, xtimer_t *timer) static void _add_timer_to_list(xtimer_t **list_head, xtimer_t *timer, uint32_t now)
{ {
while (*list_head && _timer_comparison((*list_head), timer)) { while (*list_head && _timer_comparison((*list_head), timer, now)) {
list_head = &((*list_head)->next); list_head = &((*list_head)->next);
} }
@ -227,7 +231,7 @@ static inline void _update_long_timers(uint64_t *now)
assert(timer == long_list_head); assert(timer == long_list_head);
_remove_timer_from_list(&long_list_head, timer); _remove_timer_from_list(&long_list_head, timer);
_add_timer_to_list(&timer_list_head, timer); _add_timer_to_list(&timer_list_head, timer, (uint32_t)*now);
timer = long_list_head; timer = long_list_head;
} }
else { else {