123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Copyright (c) 2018 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file
- * @brief Kernel thread timer support
- *
- * This module provides thread timer support.
- */
- #include <kernel.h>
- #include <kernel_structs.h>
- #include <thread_timer.h>
- #include <string.h>
- #undef THREAD_TIMER_DEBUG
- //#define CONFIG_THREAD_TIMER_DEBUG
- //#define THREAD_TIMER_DEBUG
- #ifdef THREAD_TIMER_DEBUG
- #include <sys/printk.h>
- #define TT_DEBUG(fmt, ...) printk("[%d] thread %p: " fmt, k_uptime_get_32(), \
- (void *)_current, ##__VA_ARGS__)
- #else
- #define TT_DEBUG(fmt, ...)
- #endif
- #define compare_time(a, b) ((int)((u32_t)(a) - (u32_t)(b)))
- #ifdef CONFIG_THREAD_TIMER_DEBUG
- static void _dump_thread_timer(struct thread_timer *ttimer)
- {
- printk("timer %p, prev: %p, next: %p\n",
- ttimer, ttimer->node.prev, ttimer->node.next);
- printk("\tthread: %p, period %d ms, delay %d ms\n",
- _current, ttimer->period, ttimer->duration);
- printk("\texpiry_time: %u, expiry_fn: %p, arg %p\n\n",
- ttimer->expiry_time,
- ttimer->expiry_fn, ttimer->expiry_fn_arg);
- }
- void _dump_thread_timer_q(void)
- {
- sys_dlist_t *thread_timer_q = &_current->thread_timer_q;
- struct thread_timer *ttimer;
- printk("thread: %p, thread_timer_q: %p, head: %p, tail: %p\n",
- _current, thread_timer_q, thread_timer_q->head,
- thread_timer_q->tail);
- SYS_DLIST_FOR_EACH_CONTAINER(thread_timer_q, ttimer, node) {
- _dump_thread_timer(ttimer);
- }
- }
- #endif
- static void _thread_timer_remove(struct k_thread *thread, struct thread_timer *ttimer)
- {
- struct thread_timer *in_q, *next;
- SYS_DLIST_FOR_EACH_CONTAINER_SAFE(&thread->thread_timer_q, in_q, next, node) {
- if (ttimer == in_q) {
- sys_dlist_remove(&in_q->node);
- return;
- }
- }
- }
- static void _thread_timer_insert(struct k_thread *thread, struct thread_timer *ttimer,
- u32_t expiry_time)
- {
- sys_dlist_t *thread_timer_q = &thread->thread_timer_q;
- struct thread_timer *in_q;
- SYS_DLIST_FOR_EACH_CONTAINER(thread_timer_q, in_q, node) {
- if (compare_time(ttimer->expiry_time, in_q->expiry_time) < 0) {
- sys_dlist_insert(&in_q->node, &ttimer->node);
- return;
- }
- }
- sys_dlist_append(thread_timer_q, &ttimer->node);
- }
- void thread_timer_init(struct thread_timer *ttimer, thread_timer_expiry_t expiry_fn,
- void *expiry_fn_arg)
- {
- __ASSERT(ttimer != NULL, "");
- if (!ttimer) {
- return;
- }
- TT_DEBUG("timer %p: init func %p arg 0x%x\n", ttimer,
- ttimer->expiry_fn, ttimer->expiry_fn_arg);
- /* remove thread timer if already submited */
- _thread_timer_remove(_current, ttimer);
- memset(ttimer, 0, sizeof(struct thread_timer));
- ttimer->expiry_fn = expiry_fn;
- ttimer->expiry_fn_arg = expiry_fn_arg;
- sys_dlist_init(&ttimer->node);
- }
- void thread_timer_start(struct thread_timer *ttimer, s32_t duration, s32_t period)
- {
- u32_t cur_time;
- if (!ttimer) {
- return;
- }
- __ASSERT((ttimer != NULL) && (ttimer->expiry_fn != NULL), "");
- _thread_timer_remove(_current, ttimer);
- cur_time = k_uptime_get_32();
- ttimer->expiry_time = cur_time + duration;
- ttimer->period = period;
- ttimer->duration = duration;
- TT_DEBUG("timer %p: start duration %d period %d, expiry_time %d\n",
- ttimer, duration, period, ttimer->expiry_time);
- _thread_timer_insert(_current, ttimer, ttimer->expiry_time);
- }
- void thread_timer_stop(struct thread_timer *ttimer)
- {
- __ASSERT(ttimer != NULL, "");
- TT_DEBUG("timer %p: stop\n", ttimer);
- _thread_timer_remove(_current, ttimer);
- }
- bool thread_timer_is_running(struct thread_timer *ttimer)
- {
- struct thread_timer *in_q;
- __ASSERT(ttimer != NULL, "");
- SYS_DLIST_FOR_EACH_CONTAINER(&_current->thread_timer_q, in_q, node) {
- if (ttimer == in_q)
- return true;
- }
- return false;
- }
- int thread_timer_next_timeout(void)
- {
- struct thread_timer *ttimer;
- int timeout;
- ttimer = SYS_DLIST_PEEK_HEAD_CONTAINER(&_current->thread_timer_q, ttimer, node);
- if (ttimer) {
- timeout = (int)((u32_t)ttimer->expiry_time - k_uptime_get_32());
- return (timeout < 0) ? 0 : timeout;
- }
- return -1;
- }
- void thread_timer_handle_expired(void)
- {
- struct thread_timer *ttimer, *next;
- u32_t cur_time;
- cur_time = k_uptime_get_32();
- SYS_DLIST_FOR_EACH_CONTAINER_SAFE(&_current->thread_timer_q, ttimer, next, node) {
- if (compare_time(ttimer->expiry_time, cur_time) > 0) {
- /* no expired thread timer */
- return;
- }
- /* remove this expiry thread timer */
- sys_dlist_remove(&ttimer->node);
- if (ttimer->expiry_fn) {
- /* resubmit this thread timer if it is a period timer */
- if (ttimer->period != 0) {
- thread_timer_start(ttimer, ttimer->period,
- ttimer->period);
- }
- TT_DEBUG("timer %p: call %p\n", ttimer, ttimer->expiry_fn);
- /* invoke thread timer expiry function */
- ttimer->expiry_fn(ttimer, ttimer->expiry_fn_arg);
- }
- }
- }
|