summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2016-10-17 14:34:53 -0500
committerBenjamin Walsh <benjamin.walsh@windriver.com>2016-10-21 15:33:29 +0000
commit6c98c4d378749ec7516addc3cf3e81e95db109cc (patch)
treed4868bbb46afccf8a2c922894b51002b3c5976db /kernel
parent811d97c32022cb7a73e01550076646928b824617 (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.c21
-rw-r--r--kernel/unified/sched.c6
-rw-r--r--kernel/unified/thread.c3
-rw-r--r--kernel/unified/timer.c7
-rw-r--r--kernel/unified/work_q.c7
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;