zephyr/kernel/timer.c
Patrik Flykt 4344e27c26 all: Update reserved function names
Update reserved function names starting with one underscore, replacing
them as follows:
   '_k_' with 'z_'
   '_K_' with 'Z_'
   '_handler_' with 'z_handl_'
   '_Cstart' with 'z_cstart'
   '_Swap' with 'z_swap'

This renaming is done on both global and those static function names
in kernel/include and include/. Other static function names in kernel/
are renamed by removing the leading underscore. Other function names
not starting with any prefix listed above are renamed starting with
a 'z_' or 'Z_' prefix.

Function names starting with two or three leading underscores are not
automatcally renamed since these names will collide with the variants
with two or three leading underscores.

Various generator scripts have also been updated as well as perf,
linker and usb files. These are
   drivers/serial/uart_handlers.c
   include/linker/kobject-text.ld
   kernel/include/syscall_handler.h
   scripts/gen_kobject_list.py
   scripts/gen_syscall_header.py

Signed-off-by: Patrik Flykt <patrik.flykt@intel.com>
2019-03-11 13:48:42 -04:00

227 lines
5.1 KiB
C

/*
* Copyright (c) 1997-2016 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <debug/object_tracing_common.h>
#include <init.h>
#include <wait_q.h>
#include <syscall_handler.h>
#include <stdbool.h>
#include <spinlock.h>
extern struct k_timer _k_timer_list_start[];
extern struct k_timer _k_timer_list_end[];
static struct k_spinlock lock;
#ifdef CONFIG_OBJECT_TRACING
struct k_timer *_trace_list_k_timer;
/*
* Complete initialization of statically defined timers.
*/
static int init_timer_module(struct device *dev)
{
ARG_UNUSED(dev);
struct k_timer *timer;
for (timer = _k_timer_list_start; timer < _k_timer_list_end; timer++) {
SYS_TRACING_OBJ_INIT(k_timer, timer);
}
return 0;
}
SYS_INIT(init_timer_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
#endif /* CONFIG_OBJECT_TRACING */
/**
* @brief Handle expiration of a kernel timer object.
*
* @param t Timeout used by the timer.
*
* @return N/A
*/
void z_timer_expiration_handler(struct _timeout *t)
{
struct k_timer *timer = CONTAINER_OF(t, struct k_timer, timeout);
struct k_thread *thread;
/*
* 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) {
z_add_timeout(&timer->timeout, z_timer_expiration_handler,
timer->period);
}
/* update timer's status */
timer->status += 1;
/* invoke timer expiry function */
if (timer->expiry_fn != NULL) {
timer->expiry_fn(timer);
}
thread = z_waitq_head(&timer->wait_q);
if (thread == NULL) {
return;
}
/*
* Interrupts _DO NOT_ have to be locked in this specific
* instance of thread unpending because a) this is the only
* place a thread can be taken off this pend queue, and b) the
* only place a thread can be put on the pend queue is at
* thread level, which of course cannot interrupt the current
* context.
*/
z_unpend_thread_no_timeout(thread);
z_ready_thread(thread);
z_set_thread_return_value(thread, 0);
}
void k_timer_init(struct k_timer *timer,
k_timer_expiry_t expiry_fn,
k_timer_stop_t stop_fn)
{
timer->expiry_fn = expiry_fn;
timer->stop_fn = stop_fn;
timer->status = 0;
z_waitq_init(&timer->wait_q);
z_init_timeout(&timer->timeout, z_timer_expiration_handler);
SYS_TRACING_OBJ_INIT(k_timer, timer);
timer->user_data = NULL;
z_object_init(timer);
}
void z_impl_k_timer_start(struct k_timer *timer, s32_t duration, s32_t period)
{
__ASSERT(duration >= 0 && period >= 0 &&
(duration != 0 || period != 0), "invalid parameters\n");
volatile s32_t period_in_ticks, duration_in_ticks;
period_in_ticks = z_ms_to_ticks(period);
duration_in_ticks = z_ms_to_ticks(duration);
(void)z_abort_timeout(&timer->timeout);
timer->period = period_in_ticks;
timer->status = 0;
z_add_timeout(&timer->timeout, z_timer_expiration_handler,
duration_in_ticks);
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(k_timer_start, timer, duration_p, period_p)
{
s32_t duration, period;
duration = (s32_t)duration_p;
period = (s32_t)period_p;
Z_OOPS(Z_SYSCALL_VERIFY(duration >= 0 && period >= 0 &&
(duration != 0 || period != 0)));
Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER));
z_impl_k_timer_start((struct k_timer *)timer, duration, period);
return 0;
}
#endif
void z_impl_k_timer_stop(struct k_timer *timer)
{
int inactive = z_abort_timeout(&timer->timeout) != 0;
if (inactive) {
return;
}
if (timer->stop_fn != NULL) {
timer->stop_fn(timer);
}
struct k_thread *pending_thread = z_unpend1_no_timeout(&timer->wait_q);
if (pending_thread != NULL) {
z_ready_thread(pending_thread);
z_reschedule_unlocked();
}
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER1_SIMPLE_VOID(k_timer_stop, K_OBJ_TIMER, struct k_timer *);
#endif
u32_t z_impl_k_timer_status_get(struct k_timer *timer)
{
k_spinlock_key_t key = k_spin_lock(&lock);
u32_t result = timer->status;
timer->status = 0;
k_spin_unlock(&lock, key);
return result;
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER1_SIMPLE(k_timer_status_get, K_OBJ_TIMER, struct k_timer *);
#endif
u32_t z_impl_k_timer_status_sync(struct k_timer *timer)
{
__ASSERT(!z_is_in_isr(), "");
k_spinlock_key_t key = k_spin_lock(&lock);
u32_t result = timer->status;
if (result == 0) {
if (!z_is_inactive_timeout(&timer->timeout)) {
/* wait for timer to expire or stop */
(void)z_pend_curr(&lock, key, &timer->wait_q, K_FOREVER);
/* get updated timer status */
key = k_spin_lock(&lock);
result = timer->status;
} else {
/* timer is already stopped */
}
} else {
/* timer has already expired at least once */
}
timer->status = 0;
k_spin_unlock(&lock, key);
return result;
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER1_SIMPLE(k_timer_status_sync, K_OBJ_TIMER, struct k_timer *);
#endif
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER1_SIMPLE(k_timer_remaining_get, K_OBJ_TIMER, struct k_timer *);
Z_SYSCALL_HANDLER1_SIMPLE(k_timer_user_data_get, K_OBJ_TIMER, struct k_timer *);
Z_SYSCALL_HANDLER(k_timer_user_data_set, timer, user_data)
{
Z_OOPS(Z_SYSCALL_OBJ(timer, K_OBJ_TIMER));
z_impl_k_timer_user_data_set((struct k_timer *)timer, (void *)user_data);
return 0;
}
#endif