| /* |
| * Copyright (c) 2016 Wind River Systems, Inc. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #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(); |
| |
| _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]; |
| static sys_dlist_t timer_pool; |
| |
| static void timer_sem_give(struct k_timer *timer) |
| { |
| k_sem_give((ksem_t)timer->user_data); |
| } |
| |
| static int init_dyamic_timers(struct device *dev) |
| { |
| ARG_UNUSED(dev); |
| |
| int i; |
| int n_timers = ARRAY_SIZE(dynamic_timers); |
| |
| sys_dlist_init(&timer_pool); |
| for (i = 0; i < n_timers; i++) { |
| k_timer_init(&dynamic_timers[i], timer_sem_give, NULL); |
| sys_dlist_append(&timer_pool, |
| &dynamic_timers[i].timeout.node); |
| } |
| return 0; |
| } |
| |
| SYS_INIT(init_dyamic_timers, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); |
| |
| ktimer_t task_timer_alloc(void) |
| { |
| _sched_lock(); |
| |
| /* |
| * This conversion works only if timeout member |
| * variable is the first in time structure. |
| */ |
| struct k_timer *timer = (struct k_timer *)sys_dlist_get(&timer_pool); |
| |
| k_sched_unlock(); |
| return timer; |
| } |
| |
| void task_timer_free(ktimer_t timer) |
| { |
| k_timer_stop(timer); |
| _sched_lock(); |
| sys_dlist_append(&timer_pool, &timer->timeout.node); |
| k_sched_unlock(); |
| } |
| |
| void task_timer_start(ktimer_t timer, int32_t duration, |
| int32_t period, ksem_t sema) |
| { |
| if (duration < 0 || period < 0 || (duration == 0 && period == 0)) { |
| k_timer_stop(timer); |
| return; |
| } |
| |
| timer->user_data = (void *)sema; |
| |
| k_timer_start(timer, _ticks_to_ms(duration), _ticks_to_ms(period)); |
| } |
| |
| bool _timer_pool_is_empty(void) |
| { |
| _sched_lock(); |
| |
| bool is_empty = sys_dlist_is_empty(&timer_pool); |
| |
| k_sched_unlock(); |
| return is_empty; |
| } |
| |
| #endif /* (CONFIG_NUM_DYNAMIC_TIMERS > 0) */ |
| |
| void *nano_timer_test(struct nano_timer *timer, int32_t timeout_in_ticks) |
| { |
| uint32_t (*test_fn)(struct k_timer *timer); |
| |
| if (timeout_in_ticks == TICKS_NONE) { |
| test_fn = k_timer_status_get; |
| } else { |
| test_fn = k_timer_status_sync; |
| } |
| return test_fn(timer) ? (void *)timer->user_data : NULL; |
| } |