diff --git a/include/kernel.h b/include/kernel.h index 30e449f1b6d..59fa082a884 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -787,9 +787,11 @@ void k_thread_system_pool_assign(struct k_thread *thread); * * @param duration Number of milliseconds to sleep. * - * @return N/A + * @return Zero if the requested time has elapsed or the number of milliseconds + * left to sleep, if thread was woken up by \ref k_wakeup call. + * */ -__syscall void k_sleep(s32_t duration); +__syscall s32_t k_sleep(s32_t duration); /** * @brief Cause the current thread to busy wait. diff --git a/kernel/sched.c b/kernel/sched.c index f914e0f3e2c..1ac656ccafd 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -793,13 +793,11 @@ void _impl_k_yield(void) Z_SYSCALL_HANDLER0_SIMPLE_VOID(k_yield); #endif -void _impl_k_sleep(s32_t duration) +s32_t _impl_k_sleep(s32_t duration) { #ifdef CONFIG_MULTITHREADING - /* volatile to guarantee that irq_lock() is executed after ticks is - * populated - */ - volatile s32_t ticks; + u32_t expected_wakeup_time; + s32_t ticks; unsigned int key; __ASSERT(!_is_in_isr(), ""); @@ -810,17 +808,25 @@ void _impl_k_sleep(s32_t duration) /* wait of 0 ms is treated as a 'yield' */ if (duration == 0) { k_yield(); - return; + return 0; } ticks = _TICK_ALIGN + _ms_to_ticks(duration); + expected_wakeup_time = ticks + z_tick_get_32(); key = irq_lock(); _remove_thread_from_ready_q(_current); _add_thread_timeout(_current, ticks); (void)_Swap(key); + + ticks = expected_wakeup_time - z_tick_get_32(); + if (ticks > 0) { + return __ticks_to_ms(ticks); + } #endif + + return 0; } #ifdef CONFIG_USERSPACE @@ -831,9 +837,8 @@ Z_SYSCALL_HANDLER(k_sleep, duration) */ Z_OOPS(Z_SYSCALL_VERIFY_MSG(duration != K_FOREVER, "sleeping forever not allowed")); - _impl_k_sleep(duration); - return 0; + return _impl_k_sleep(duration); } #endif