diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2016-10-17 14:34:53 -0500 |
---|---|---|
committer | Benjamin Walsh <benjamin.walsh@windriver.com> | 2016-10-21 15:33:29 +0000 |
commit | 6c98c4d378749ec7516addc3cf3e81e95db109cc (patch) | |
tree | d4868bbb46afccf8a2c922894b51002b3c5976db /kernel | |
parent | 811d97c32022cb7a73e01550076646928b824617 (diff) |
unified: Ensure delays do not time out prematurely
Ensures that all APIs which accept a timeout value wait for at least
the specified amount of time, and do not time out prematurely.
* The kernel now waits for the next system clock tick to occur before
the timeout interval is considered to have started. (That is, the only
way to ensure a delay of N tick intervals is to wait for N+1 ticks
to occur.)
* Gets rid of ticks -> milliseconds -> ticks conversion in task_sleep()
and fiber_sleep() legacy APIs, since this introduces rounding that
-- coupled with the previous change -- can alter the number of ticks
being requested during the sleep operation.
* Corrects work queue API that was incorrectly shown to use a delay
measured in ticks, rather than milliseconds.
Change-Id: I8b04467237b24fb0364c8f344d872457418c18da
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/unified/legacy/timer_legacy.c | 21 | ||||
-rw-r--r-- | kernel/unified/sched.c | 6 | ||||
-rw-r--r-- | kernel/unified/thread.c | 3 | ||||
-rw-r--r-- | kernel/unified/timer.c | 7 | ||||
-rw-r--r-- | kernel/unified/work_q.c | 7 |
5 files changed, 36 insertions, 8 deletions
diff --git a/kernel/unified/legacy/timer_legacy.c b/kernel/unified/legacy/timer_legacy.c index b70edfdca..1e61f93bf 100644 --- a/kernel/unified/legacy/timer_legacy.c +++ b/kernel/unified/legacy/timer_legacy.c @@ -17,8 +17,29 @@ #include <kernel.h> #include <init.h> #include <ksched.h> +#include <wait_q.h> +#include <misc/__assert.h> #include <misc/util.h> +void _legacy_sleep(int32_t ticks) +{ + __ASSERT(!_is_in_isr(), ""); + __ASSERT(ticks != TICKS_UNLIMITED, ""); + + if (ticks <= 0) { + k_yield(); + return; + } + + int key = irq_lock(); + + _mark_thread_as_timing(_current); + _remove_thread_from_ready_q(_current); + _add_thread_timeout(_current, NULL, ticks); + + _Swap(key); +} + #if (CONFIG_NUM_DYNAMIC_TIMERS > 0) static struct k_timer dynamic_timers[CONFIG_NUM_DYNAMIC_TIMERS]; diff --git a/kernel/unified/sched.c b/kernel/unified/sched.c index a03b13870..44c5a2bd4 100644 --- a/kernel/unified/sched.c +++ b/kernel/unified/sched.c @@ -152,7 +152,8 @@ void _pend_thread(struct k_thread *thread, _wait_q_t *wait_q, int32_t timeout) if (timeout != K_FOREVER) { _mark_thread_as_timing(thread); - _add_thread_timeout(thread, wait_q, _ms_to_ticks(timeout)); + _add_thread_timeout(thread, wait_q, + _TICK_ALIGN + _ms_to_ticks(timeout)); } } @@ -296,7 +297,8 @@ void k_sleep(int32_t duration) _mark_thread_as_timing(_current); _remove_thread_from_ready_q(_current); - _add_thread_timeout(_current, NULL, _ms_to_ticks(duration)); + _add_thread_timeout(_current, NULL, + _TICK_ALIGN + _ms_to_ticks(duration)); _Swap(key); } diff --git a/kernel/unified/thread.c b/kernel/unified/thread.c index 06e247aa1..ed2c7a293 100644 --- a/kernel/unified/thread.c +++ b/kernel/unified/thread.c @@ -271,7 +271,8 @@ static void schedule_new_thread(struct k_thread *thread, int32_t delay) start_thread(thread); } else { _mark_thread_as_timing(thread); - _add_thread_timeout(thread, NULL, _ms_to_ticks(delay)); + _add_thread_timeout(thread, NULL, + _TICK_ALIGN + _ms_to_ticks(delay)); } #else ARG_UNUSED(delay); diff --git a/kernel/unified/timer.c b/kernel/unified/timer.c index 776690198..4485311ab 100644 --- a/kernel/unified/timer.c +++ b/kernel/unified/timer.c @@ -31,7 +31,10 @@ static void timer_expiration_handler(struct _timeout *t) struct k_timer *timer = CONTAINER_OF(t, struct k_timer, timeout); struct k_thread *pending_thread; - /* if the time is periodic, start it again */ + /* + * if the timer is periodic, start it again; don't add _TICK_ALIGN + * since we're already aligned to a tick boundary + */ if (timer->period > 0) { _add_timeout(NULL, &timer->timeout, &timer->wait_q, timer->period); @@ -87,7 +90,7 @@ void k_timer_start(struct k_timer *timer, int32_t duration, int32_t period) timer->period = _ms_to_ticks(period); _add_timeout(NULL, &timer->timeout, &timer->wait_q, - _ms_to_ticks(duration)); + _TICK_ALIGN + _ms_to_ticks(duration)); timer->status = 0; irq_unlock(key); } diff --git a/kernel/unified/work_q.c b/kernel/unified/work_q.c index 6bd3c3e00..4c3a2bebe 100644 --- a/kernel/unified/work_q.c +++ b/kernel/unified/work_q.c @@ -81,7 +81,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler) int k_delayed_work_submit_to_queue(struct k_work_q *work_q, struct k_delayed_work *work, - int32_t timeout) + int32_t delay) { int key = irq_lock(); int err; @@ -103,12 +103,13 @@ int k_delayed_work_submit_to_queue(struct k_work_q *work_q, /* Attach workqueue so the timeout callback can submit it */ work->work_q = work_q; - if (!timeout) { + if (!delay) { /* Submit work if no ticks is 0 */ k_work_submit_to_queue(work_q, &work->work); } else { /* Add timeout */ - _add_timeout(NULL, &work->timeout, NULL, _ms_to_ticks(timeout)); + _add_timeout(NULL, &work->timeout, NULL, + _TICK_ALIGN + _ms_to_ticks(delay)); } err = 0; |