Merge pull request #4903 from kaspar030/xtimer_fixes

sys: xtimer: fix some race conditions
This commit is contained in:
Martine Lenders 2016-03-12 00:18:56 +01:00
commit b3b880be6a
2 changed files with 24 additions and 22 deletions

View File

@ -251,11 +251,8 @@ void xtimer_set(xtimer_t *timer, uint32_t offset);
* @note this function runs in O(n) with n being the number of active timers * @note this function runs in O(n) with n being the number of active timers
* *
* @param[in] timer ptr to timer structure that will be removed * @param[in] timer ptr to timer structure that will be removed
*
* @return 1 on success
* @return 0 when timer was not active
*/ */
int xtimer_remove(xtimer_t *timer); void xtimer_remove(xtimer_t *timer);
/** /**
* @brief receive a message blocking but with timeout * @brief receive a message blocking but with timeout

View File

@ -40,6 +40,7 @@ static xtimer_t *long_list_head = NULL;
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);
static void _add_timer_to_long_list(xtimer_t **list_head, xtimer_t *timer); static void _add_timer_to_long_list(xtimer_t **list_head, xtimer_t *timer);
static void _shoot(xtimer_t *timer); static void _shoot(xtimer_t *timer);
static void _remove(xtimer_t *timer);
static inline void _lltimer_set(uint32_t target); static inline void _lltimer_set(uint32_t target);
static uint32_t _time_left(uint32_t target, uint32_t reference); static uint32_t _time_left(uint32_t target, uint32_t reference);
@ -94,7 +95,10 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
xtimer_set(timer, (uint32_t) offset); xtimer_set(timer, (uint32_t) offset);
} }
else { else {
xtimer_remove(timer); int state = disableIRQ();
if (_is_set(timer)) {
_remove(timer);
}
_xtimer_now64(&timer->target, &timer->long_target); _xtimer_now64(&timer->target, &timer->long_target);
timer->target += offset; timer->target += offset;
@ -103,7 +107,6 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
timer->long_target++; timer->long_target++;
} }
int state = disableIRQ();
_add_timer_to_long_list(&long_list_head, timer); _add_timer_to_long_list(&long_list_head, timer);
restoreIRQ(state); restoreIRQ(state);
DEBUG("xtimer_set64(): added longterm timer (long_target=%" PRIu32 " target=%" PRIu32 ")\n", DEBUG("xtimer_set64(): added longterm timer (long_target=%" PRIu32 " target=%" PRIu32 ")\n",
@ -173,13 +176,17 @@ int _xtimer_set_absolute(xtimer_t *timer, uint32_t target)
return 0; return 0;
} }
unsigned state = disableIRQ();
if (_is_set(timer)) {
_remove(timer);
}
timer->target = target; timer->target = target;
timer->long_target = _long_cnt; timer->long_target = _long_cnt;
if (target < now) { if (target < now) {
timer->long_target++; timer->long_target++;
} }
unsigned state = disableIRQ();
if ( (timer->long_target > _long_cnt) || !_this_high_period(target) ) { if ( (timer->long_target > _long_cnt) || !_this_high_period(target) ) {
DEBUG("xtimer_set_absolute(): the timer doesn't fit into the low-level timer's mask.\n"); DEBUG("xtimer_set_absolute(): the timer doesn't fit into the low-level timer's mask.\n");
_add_timer_to_long_list(&long_list_head, timer); _add_timer_to_long_list(&long_list_head, timer);
@ -240,14 +247,8 @@ static int _remove_timer_from_list(xtimer_t **list_head, xtimer_t *timer)
return 0; return 0;
} }
int xtimer_remove(xtimer_t *timer) static void _remove(xtimer_t *timer)
{ {
if (!_is_set(timer)) {
return 0;
}
unsigned state = disableIRQ();
int res = 0;
if (timer_list_head == timer) { if (timer_list_head == timer) {
uint32_t next; uint32_t next;
timer_list_head = timer->next; timer_list_head = timer->next;
@ -261,17 +262,21 @@ int xtimer_remove(xtimer_t *timer)
_lltimer_set(next); _lltimer_set(next);
} }
else { else {
res = _remove_timer_from_list(&timer_list_head, timer) || if (!_remove_timer_from_list(&timer_list_head, timer)) {
_remove_timer_from_list(&overflow_list_head, timer) || if (!_remove_timer_from_list(&overflow_list_head, timer)) {
_remove_timer_from_list(&long_list_head, timer); _remove_timer_from_list(&long_list_head, timer);
}
}
} }
}
timer->target = 0; void xtimer_remove(xtimer_t *timer)
timer->long_target = 0; {
int state = disableIRQ();
if (_is_set(timer)) {
_remove(timer);
}
restoreIRQ(state); restoreIRQ(state);
return res;
} }
static uint32_t _time_left(uint32_t target, uint32_t reference) static uint32_t _time_left(uint32_t target, uint32_t reference)