kernel: sched: Make k_sleep() similar to POSIX equivalent

This commit introduces k_sleep() return value, which provides
information about actual sleep time. If the returned value is
not-zero, the thread slept shorter than requested, which is
only possible if the thread has been woken up by k_wakeup() call.

Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
This commit is contained in:
Piotr Zięcik 2018-10-25 17:45:08 +02:00 committed by Carles Cufí
commit 7700eb2a15
2 changed files with 17 additions and 10 deletions

View file

@ -787,9 +787,11 @@ void k_thread_system_pool_assign(struct k_thread *thread);
* *
* @param duration Number of milliseconds to sleep. * @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. * @brief Cause the current thread to busy wait.

View file

@ -793,13 +793,11 @@ void _impl_k_yield(void)
Z_SYSCALL_HANDLER0_SIMPLE_VOID(k_yield); Z_SYSCALL_HANDLER0_SIMPLE_VOID(k_yield);
#endif #endif
void _impl_k_sleep(s32_t duration) s32_t _impl_k_sleep(s32_t duration)
{ {
#ifdef CONFIG_MULTITHREADING #ifdef CONFIG_MULTITHREADING
/* volatile to guarantee that irq_lock() is executed after ticks is u32_t expected_wakeup_time;
* populated s32_t ticks;
*/
volatile s32_t ticks;
unsigned int key; unsigned int key;
__ASSERT(!_is_in_isr(), ""); __ASSERT(!_is_in_isr(), "");
@ -810,17 +808,25 @@ void _impl_k_sleep(s32_t duration)
/* wait of 0 ms is treated as a 'yield' */ /* wait of 0 ms is treated as a 'yield' */
if (duration == 0) { if (duration == 0) {
k_yield(); k_yield();
return; return 0;
} }
ticks = _TICK_ALIGN + _ms_to_ticks(duration); ticks = _TICK_ALIGN + _ms_to_ticks(duration);
expected_wakeup_time = ticks + z_tick_get_32();
key = irq_lock(); key = irq_lock();
_remove_thread_from_ready_q(_current); _remove_thread_from_ready_q(_current);
_add_thread_timeout(_current, ticks); _add_thread_timeout(_current, ticks);
(void)_Swap(key); (void)_Swap(key);
ticks = expected_wakeup_time - z_tick_get_32();
if (ticks > 0) {
return __ticks_to_ms(ticks);
}
#endif #endif
return 0;
} }
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
@ -831,9 +837,8 @@ Z_SYSCALL_HANDLER(k_sleep, duration)
*/ */
Z_OOPS(Z_SYSCALL_VERIFY_MSG(duration != K_FOREVER, Z_OOPS(Z_SYSCALL_VERIFY_MSG(duration != K_FOREVER,
"sleeping forever not allowed")); "sleeping forever not allowed"));
_impl_k_sleep(duration);
return 0; return _impl_k_sleep(duration);
} }
#endif #endif