zephyr/kernel/alert.c

111 lines
2.5 KiB
C
Raw Normal View History

/*
* Copyright (c) 2016 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief kernel alerts.
*/
#include <kernel.h>
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 23:36:50 +08:00
#include <kernel_structs.h>
#include <debug/object_tracing_common.h>
#include <atomic.h>
#include <init.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <syscall_handler.h>
#include <stdbool.h>
extern struct k_alert _k_alert_list_start[];
extern struct k_alert _k_alert_list_end[];
struct k_alert *_trace_list_k_alert;
#ifdef CONFIG_OBJECT_TRACING
/*
* Complete initialization of statically defined alerts.
*/
static int init_alert_module(struct device *dev)
{
ARG_UNUSED(dev);
struct k_alert *alert;
for (alert = _k_alert_list_start; alert < _k_alert_list_end; alert++) {
SYS_TRACING_OBJ_INIT(k_alert, alert);
}
return 0;
}
SYS_INIT(init_alert_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
#endif /* CONFIG_OBJECT_TRACING */
void _alert_deliver(struct k_work *work)
{
struct k_alert *alert = CONTAINER_OF(work, struct k_alert, work_item);
while (true) {
if ((alert->handler)(alert) == 0) {
/* do nothing -- handler has processed the alert */
} else {
/* pend the alert */
k_sem_give(&alert->sem);
}
if (atomic_dec(&alert->send_count) == 1) {
/* have finished delivering alerts */
break;
}
}
}
void k_alert_init(struct k_alert *alert, k_alert_handler_t handler,
unsigned int max_num_pending_alerts)
{
alert->handler = handler;
alert->send_count = ATOMIC_INIT(0);
alert->work_item = (struct k_work)_K_WORK_INITIALIZER(_alert_deliver);
k_sem_init(&alert->sem, 0, max_num_pending_alerts);
SYS_TRACING_OBJ_INIT(k_alert, alert);
kernel: introduce object validation mechanism All system calls made from userspace which involve pointers to kernel objects (including device drivers) will need to have those pointers validated; userspace should never be able to crash the kernel by passing it garbage. The actual validation with _k_object_validate() will be in the system call receiver code, which doesn't exist yet. - CONFIG_USERSPACE introduced. We are somewhat far away from having an end-to-end implementation, but at least need a Kconfig symbol to guard the incoming code with. Formal documentation doesn't exist yet either, but will appear later down the road once the implementation is mostly finalized. - In the memory region for RAM, the data section has been moved last, past bss and noinit. This ensures that inserting generated tables with addresses of kernel objects does not change the addresses of those objects (which would make the table invalid) - The DWARF debug information in the generated ELF binary is parsed to fetch the locations of all kernel objects and pass this to gperf to create a perfect hash table of their memory addresses. - The generated gperf code doesn't know that we are exclusively working with memory addresses and uses memory inefficently. A post-processing script process_gperf.py adjusts the generated code before it is compiled to work with pointer values directly and not strings containing them. - _k_object_init() calls inserted into the init functions for the set of kernel object types we are going to support so far Issue: ZEP-2187 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-08-23 04:15:23 +08:00
_k_object_init(alert);
}
void _impl_k_alert_send(struct k_alert *alert)
{
if (alert->handler == K_ALERT_IGNORE) {
/* ignore the alert */
} else if (alert->handler == K_ALERT_DEFAULT) {
/* pend the alert */
k_sem_give(&alert->sem);
} else {
/* deliver the alert */
if (atomic_inc(&alert->send_count) == 0) {
/* add alert's work item to system work queue */
k_work_submit_to_queue(&k_sys_work_q,
&alert->work_item);
}
}
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER1_SIMPLE_VOID(k_alert_send, K_OBJ_ALERT, struct k_alert *);
#endif
int _impl_k_alert_recv(struct k_alert *alert, s32_t timeout)
{
return k_sem_take(&alert->sem, timeout);
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(k_alert_recv, alert, timeout)
{
Z_OOPS(Z_SYSCALL_OBJ(alert, K_OBJ_ALERT));
return _impl_k_alert_recv((struct k_alert *)alert, timeout);
}
#endif