kernel: remove k_alert API
This API was used in only one place in non-test code. See whether we can remove it. Closes #12232 Signed-off-by: Peter A. Bigot <pab@pabigot.com>
This commit is contained in:
parent
b026a34026
commit
bfad9721d2
20 changed files with 2 additions and 1266 deletions
|
@ -109,16 +109,6 @@ with basic priority inheritance.
|
||||||
.. doxygengroup:: mutex_apis
|
.. doxygengroup:: mutex_apis
|
||||||
:project: Zephyr
|
:project: Zephyr
|
||||||
|
|
||||||
Alerts
|
|
||||||
******
|
|
||||||
|
|
||||||
Alerts enable an application to perform asynchronous signaling,
|
|
||||||
somewhat akin to Unix-style signals.
|
|
||||||
(See :ref:`alerts_v2`.)
|
|
||||||
|
|
||||||
.. doxygengroup:: alert_apis
|
|
||||||
:project: Zephyr
|
|
||||||
|
|
||||||
FIFOs
|
FIFOs
|
||||||
*****
|
*****
|
||||||
|
|
||||||
|
|
|
@ -166,12 +166,8 @@ processing to a thread.
|
||||||
* An ISR can signal a helper thread to do interrupt-related processing
|
* An ISR can signal a helper thread to do interrupt-related processing
|
||||||
using a kernel object, such as a fifo, lifo, or semaphore.
|
using a kernel object, such as a fifo, lifo, or semaphore.
|
||||||
|
|
||||||
* An ISR can signal an alert which causes the system workqueue thread
|
|
||||||
to execute an associated alert handler function.
|
|
||||||
(See :ref:`alerts_v2`.)
|
|
||||||
|
|
||||||
* An ISR can instruct the system workqueue thread to execute a work item.
|
* An ISR can instruct the system workqueue thread to execute a work item.
|
||||||
(See TBD.)
|
(See :ref:`workqueues_v2`.)
|
||||||
|
|
||||||
When an ISR offloads work to a thread, there is typically a single context
|
When an ISR offloads work to a thread, there is typically a single context
|
||||||
switch to that thread when the ISR completes, allowing interrupt-related
|
switch to that thread when the ISR completes, allowing interrupt-related
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
.. _alerts_v2:
|
|
||||||
|
|
||||||
Alerts
|
|
||||||
######
|
|
||||||
|
|
||||||
An :dfn:`alert` is a kernel object that allows an application to perform
|
|
||||||
asynchronous signaling when a condition of interest occurs.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 2
|
|
||||||
|
|
||||||
Concepts
|
|
||||||
********
|
|
||||||
|
|
||||||
Any number of alerts can be defined. Each alert is referenced by
|
|
||||||
its memory address.
|
|
||||||
|
|
||||||
An alert has the following key properties:
|
|
||||||
|
|
||||||
* An **alert handler**, which specifies the action to be taken
|
|
||||||
when the alert is signaled. The action may instruct the system workqueue
|
|
||||||
to execute a function to process the alert, mark the alert as pending
|
|
||||||
so it can be processed later by a thread, or ignore the alert.
|
|
||||||
|
|
||||||
* An **pending count**, which records the number of pending alerts
|
|
||||||
that have yet to be received.
|
|
||||||
|
|
||||||
* An **count limit**, which specifies the maximum number of pending alerts
|
|
||||||
that will be recorded.
|
|
||||||
|
|
||||||
An alert must be initialized before it can be used. This establishes
|
|
||||||
its alert handler and sets the pending count to zero.
|
|
||||||
|
|
||||||
Alert Lifecycle
|
|
||||||
===============
|
|
||||||
|
|
||||||
An ISR or a thread signals an alert by **sending** the alert
|
|
||||||
when a condition of interest occurs that cannot be handled by the detector.
|
|
||||||
|
|
||||||
Each time an alert is sent, the kernel examines its alert handler
|
|
||||||
to determine what action to take.
|
|
||||||
|
|
||||||
* :c:macro:`K_ALERT_IGNORE` causes the alert to be ignored.
|
|
||||||
|
|
||||||
* :c:macro:`K_ALERT_DEFAULT` causes the pending count to be incremented,
|
|
||||||
unless this would exceed the count limit.
|
|
||||||
|
|
||||||
* Any other value is assumed to be the address of an alert handler function,
|
|
||||||
and is invoked by the system workqueue thread. If the function returns
|
|
||||||
zero, the signal is deemed to have been consumed; otherwise the pending
|
|
||||||
count is incremented, unless this would exceed the count limit.
|
|
||||||
|
|
||||||
The kernel ensures that the alert handler function is executed once
|
|
||||||
for each time an alert is sent, even if the alert is sent multiple times
|
|
||||||
in rapid succession.
|
|
||||||
|
|
||||||
A thread accepts a pending alert by **receiving** the alert.
|
|
||||||
This decrements the pending count. If the pending count is currently zero,
|
|
||||||
the thread may choose to wait for the alert to become pending.
|
|
||||||
Any number of threads may wait for a pending alert simultaneously;
|
|
||||||
when the alert is pended it is accepted by the highest priority thread
|
|
||||||
that has waited longest.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
A thread must processes pending alerts one at a time. The thread
|
|
||||||
cannot receive multiple pending alerts in a single operation.
|
|
||||||
|
|
||||||
Comparison to Unix-style Signals
|
|
||||||
================================
|
|
||||||
|
|
||||||
Zephyr alerts are somewhat akin to Unix-style signals, but have a number of
|
|
||||||
significant differences. The most notable of these are:
|
|
||||||
|
|
||||||
* A Zephyr alert cannot be blocked; it is always delivered to its alert
|
|
||||||
handler immediately.
|
|
||||||
|
|
||||||
* A Zephyr alert pends *after* it has been delivered to its alert handler,
|
|
||||||
and only if an alert handler function does not consume the alert.
|
|
||||||
|
|
||||||
* Zephyr has no predefined alerts or actions. All alerts are application
|
|
||||||
defined, and all have a default action that pends the alert.
|
|
||||||
|
|
||||||
Implementation
|
|
||||||
**************
|
|
||||||
|
|
||||||
Defining an Alert
|
|
||||||
=================
|
|
||||||
|
|
||||||
An alert is defined using a variable of type :c:type:`struct k_alert`.
|
|
||||||
It must then be initialized by calling :cpp:func:`k_alert_init()`.
|
|
||||||
|
|
||||||
The following code defines and initializes an alert. The alert allows
|
|
||||||
up to 10 unreceived alert signals to pend before it begins to ignore
|
|
||||||
new pending alerts.
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
extern int my_alert_handler(struct k_alert *alert);
|
|
||||||
|
|
||||||
struct k_alert my_alert;
|
|
||||||
|
|
||||||
k_alert_init(&my_alert, my_alert_handler, 10);
|
|
||||||
|
|
||||||
Alternatively, an alert can be defined and initialized at compile time
|
|
||||||
by calling :c:macro:`K_ALERT_DEFINE`.
|
|
||||||
|
|
||||||
The following code has the same effect as the code segment above.
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
extern int my_alert_handler(struct k_alert *alert);
|
|
||||||
|
|
||||||
K_ALERT_DEFINE(my_alert, my_alert_handler, 10);
|
|
||||||
|
|
||||||
Signaling an Alert
|
|
||||||
==================
|
|
||||||
|
|
||||||
An alert is signaled by calling :cpp:func:`k_alert_send()`.
|
|
||||||
|
|
||||||
The following code illustrates how an ISR can signal an alert
|
|
||||||
to indicate that a key press has occurred.
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
extern int my_alert_handler(struct k_alert *alert);
|
|
||||||
|
|
||||||
K_ALERT_DEFINE(my_alert, my_alert_handler, 10);
|
|
||||||
|
|
||||||
void keypress_interrupt_handler(void *arg)
|
|
||||||
{
|
|
||||||
...
|
|
||||||
k_alert_send(&my_alert);
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
Handling an Alert
|
|
||||||
=================
|
|
||||||
|
|
||||||
An alert handler function is used when a signaled alert should not be ignored
|
|
||||||
or immediately pended. It has the following form:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
int <function_name>(struct k_alert *alert)
|
|
||||||
{
|
|
||||||
/* catch the alert signal; return zero if the signal is consumed, */
|
|
||||||
/* or non-zero to let the alert pend */
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
The following code illustrates an alert handler function that processes
|
|
||||||
key presses detected by an ISR (as shown in the previous section).
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
int my_alert_handler(struct k_alert *alert_id_is_unused)
|
|
||||||
{
|
|
||||||
/* determine what key was pressed */
|
|
||||||
char c = get_keypress();
|
|
||||||
|
|
||||||
/* do complex processing of the keystroke */
|
|
||||||
...
|
|
||||||
|
|
||||||
/* signaled alert has been consumed */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Accepting an Alert
|
|
||||||
==================
|
|
||||||
|
|
||||||
A pending alert is accepted by a thread by calling :cpp:func:`k_alert_recv()`.
|
|
||||||
|
|
||||||
The following code is an alternative to the code in the previous section.
|
|
||||||
It uses a dedicated thread to do very complex processing
|
|
||||||
of key presses that would otherwise monopolize the system workqueue.
|
|
||||||
The alert handler function is now used only to filter out unwanted key press
|
|
||||||
alerts, allowing the dedicated thread to wake up and process key press alerts
|
|
||||||
only when a numeric key is pressed.
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
int my_alert_handler(struct k_alert *alert_id_is_unused)
|
|
||||||
{
|
|
||||||
/* determine what key was pressed */
|
|
||||||
char c = get_keypress();
|
|
||||||
|
|
||||||
/* signal thread only if key pressed was a digit */
|
|
||||||
if ((c >= '0') && (c <= '9')) {
|
|
||||||
/* save key press information */
|
|
||||||
...
|
|
||||||
/* signaled alert should be pended */
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
/* signaled alert has been consumed */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void keypress_thread(void *unused1, void *unused2, void *unused3)
|
|
||||||
{
|
|
||||||
/* consume numeric key presses */
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
/* wait for a key press alert to pend */
|
|
||||||
k_alert_recv(&my_alert, K_FOREVER);
|
|
||||||
|
|
||||||
/* process saved key press, which must be a digit */
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Suggested Uses
|
|
||||||
**************
|
|
||||||
|
|
||||||
Use an alert to minimize ISR processing by deferring interrupt-related
|
|
||||||
work to a thread to reduce the amount of time interrupts are locked.
|
|
||||||
|
|
||||||
Use an alert to allow the kernel's system workqueue to handle an alert,
|
|
||||||
rather than defining an application thread to handle it.
|
|
||||||
|
|
||||||
Use an alert to allow the kernel's system workqueue to preprocess an alert,
|
|
||||||
prior to letting an application thread handle it.
|
|
||||||
|
|
||||||
Configuration Options
|
|
||||||
*********************
|
|
||||||
|
|
||||||
Related configuration options:
|
|
||||||
|
|
||||||
* None.
|
|
||||||
|
|
||||||
APIs
|
|
||||||
****
|
|
||||||
|
|
||||||
The following alert APIs are provided by :file:`kernel.h`:
|
|
||||||
|
|
||||||
* :c:macro:`K_ALERT_DEFINE`
|
|
||||||
* :cpp:func:`k_alert_init()`
|
|
||||||
* :cpp:func:`k_alert_send()`
|
|
||||||
* :cpp:func:`k_alert_recv()`
|
|
|
@ -11,4 +11,3 @@ of different threads, or the operation of an ISR and a thread.
|
||||||
|
|
||||||
semaphores.rst
|
semaphores.rst
|
||||||
mutexes.rst
|
mutexes.rst
|
||||||
alerts.rst
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ extern struct k_mem_slab *_trace_list_k_mem_slab;
|
||||||
extern struct k_mem_pool *_trace_list_k_mem_pool;
|
extern struct k_mem_pool *_trace_list_k_mem_pool;
|
||||||
extern struct k_sem *_trace_list_k_sem;
|
extern struct k_sem *_trace_list_k_sem;
|
||||||
extern struct k_mutex *_trace_list_k_mutex;
|
extern struct k_mutex *_trace_list_k_mutex;
|
||||||
extern struct k_alert *_trace_list_k_alert;
|
|
||||||
extern struct k_fifo *_trace_list_k_fifo;
|
extern struct k_fifo *_trace_list_k_fifo;
|
||||||
extern struct k_lifo *_trace_list_k_lifo;
|
extern struct k_lifo *_trace_list_k_lifo;
|
||||||
extern struct k_stack *_trace_list_k_stack;
|
extern struct k_stack *_trace_list_k_stack;
|
||||||
|
|
145
include/kernel.h
145
include/kernel.h
|
@ -115,7 +115,6 @@ typedef struct {
|
||||||
struct k_thread;
|
struct k_thread;
|
||||||
struct k_mutex;
|
struct k_mutex;
|
||||||
struct k_sem;
|
struct k_sem;
|
||||||
struct k_alert;
|
|
||||||
struct k_msgq;
|
struct k_msgq;
|
||||||
struct k_mbox;
|
struct k_mbox;
|
||||||
struct k_pipe;
|
struct k_pipe;
|
||||||
|
@ -3071,150 +3070,6 @@ static inline unsigned int _impl_k_sem_count_get(struct k_sem *sem)
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup alert_apis Alert APIs
|
|
||||||
* @ingroup kernel_apis
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef k_alert_handler_t
|
|
||||||
* @brief Alert handler function type.
|
|
||||||
*
|
|
||||||
* An alert's alert handler function is invoked by the system workqueue
|
|
||||||
* when the alert is signaled. The alert handler function is optional,
|
|
||||||
* and is only invoked if the alert has been initialized with one.
|
|
||||||
*
|
|
||||||
* @param alert Address of the alert.
|
|
||||||
*
|
|
||||||
* @return 0 if alert has been consumed; non-zero if alert should pend.
|
|
||||||
*/
|
|
||||||
typedef int (*k_alert_handler_t)(struct k_alert *alert);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond INTERNAL_HIDDEN
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define K_ALERT_DEFAULT NULL
|
|
||||||
#define K_ALERT_IGNORE ((k_alert_handler_t)0xFFFFFFFF)
|
|
||||||
|
|
||||||
struct k_alert {
|
|
||||||
k_alert_handler_t handler;
|
|
||||||
atomic_t send_count;
|
|
||||||
struct k_work work_item;
|
|
||||||
struct k_sem sem;
|
|
||||||
|
|
||||||
_OBJECT_TRACING_NEXT_PTR(k_alert)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
extern void _alert_deliver(struct k_work *work);
|
|
||||||
|
|
||||||
#define _K_ALERT_INITIALIZER(obj, alert_handler, max_num_pending_alerts) \
|
|
||||||
{ \
|
|
||||||
.handler = (k_alert_handler_t)alert_handler, \
|
|
||||||
.send_count = ATOMIC_INIT(0), \
|
|
||||||
.work_item = _K_WORK_INITIALIZER(_alert_deliver), \
|
|
||||||
.sem = _K_SEM_INITIALIZER(obj.sem, 0, max_num_pending_alerts), \
|
|
||||||
_OBJECT_TRACING_INIT \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define K_ALERT_INITIALIZER DEPRECATED_MACRO _K_ALERT_INITIALIZER
|
|
||||||
|
|
||||||
/**
|
|
||||||
* INTERNAL_HIDDEN @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @addtogroup alert_apis
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @def K_ALERT_DEFINE(name, alert_handler, max_num_pending_alerts)
|
|
||||||
*
|
|
||||||
* @brief Statically define and initialize an alert.
|
|
||||||
*
|
|
||||||
* The alert can be accessed outside the module where it is defined using:
|
|
||||||
*
|
|
||||||
* @code extern struct k_alert <name>; @endcode
|
|
||||||
*
|
|
||||||
* @param name Name of the alert.
|
|
||||||
* @param alert_handler Action to take when alert is sent. Specify either
|
|
||||||
* the address of a function to be invoked by the system workqueue
|
|
||||||
* thread, K_ALERT_IGNORE (which causes the alert to be ignored), or
|
|
||||||
* K_ALERT_DEFAULT (which causes the alert to pend).
|
|
||||||
* @param max_num_pending_alerts Maximum number of pending alerts.
|
|
||||||
*
|
|
||||||
* @req K-ALERT-001
|
|
||||||
*/
|
|
||||||
#define K_ALERT_DEFINE(name, alert_handler, max_num_pending_alerts) \
|
|
||||||
struct k_alert name \
|
|
||||||
__in_section(_k_alert, static, name) = \
|
|
||||||
_K_ALERT_INITIALIZER(name, alert_handler, \
|
|
||||||
max_num_pending_alerts)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize an alert.
|
|
||||||
*
|
|
||||||
* This routine initializes an alert object, prior to its first use.
|
|
||||||
*
|
|
||||||
* @param alert Address of the alert.
|
|
||||||
* @param handler Action to take when alert is sent. Specify either the address
|
|
||||||
* of a function to be invoked by the system workqueue thread,
|
|
||||||
* K_ALERT_IGNORE (which causes the alert to be ignored), or
|
|
||||||
* K_ALERT_DEFAULT (which causes the alert to pend).
|
|
||||||
* @param max_num_pending_alerts Maximum number of pending alerts.
|
|
||||||
*
|
|
||||||
* @return N/A
|
|
||||||
* @req K-ALERT-002
|
|
||||||
*/
|
|
||||||
extern void k_alert_init(struct k_alert *alert, k_alert_handler_t handler,
|
|
||||||
unsigned int max_num_pending_alerts);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Receive an alert.
|
|
||||||
*
|
|
||||||
* This routine receives a pending alert for @a alert.
|
|
||||||
*
|
|
||||||
* @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
|
|
||||||
*
|
|
||||||
* @param alert Address of the alert.
|
|
||||||
* @param timeout Waiting period to receive the alert (in milliseconds),
|
|
||||||
* or one of the special values K_NO_WAIT and K_FOREVER.
|
|
||||||
*
|
|
||||||
* @retval 0 Alert received.
|
|
||||||
* @retval -EBUSY Returned without waiting.
|
|
||||||
* @retval -EAGAIN Waiting period timed out.
|
|
||||||
* @req K-ALERT-002
|
|
||||||
*/
|
|
||||||
__syscall int k_alert_recv(struct k_alert *alert, s32_t timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Signal an alert.
|
|
||||||
*
|
|
||||||
* This routine signals @a alert. The action specified for @a alert will
|
|
||||||
* be taken, which may trigger the execution of an alert handler function
|
|
||||||
* and/or cause the alert to pend (assuming the alert has not reached its
|
|
||||||
* maximum number of pending alerts).
|
|
||||||
*
|
|
||||||
* @note Can be called by ISRs.
|
|
||||||
*
|
|
||||||
* @param alert Address of the alert.
|
|
||||||
*
|
|
||||||
* @return N/A
|
|
||||||
* @req K-ALERT-002
|
|
||||||
*/
|
|
||||||
__syscall void k_alert_send(struct k_alert *alert);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup msgq_apis Message Queue APIs
|
* @defgroup msgq_apis Message Queue APIs
|
||||||
* @ingroup kernel_apis
|
* @ingroup kernel_apis
|
||||||
|
|
|
@ -83,13 +83,6 @@
|
||||||
_k_mutex_list_end = .;
|
_k_mutex_list_end = .;
|
||||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||||
|
|
||||||
SECTION_DATA_PROLOGUE(_k_alert_area, (OPTIONAL), SUBALIGN(4))
|
|
||||||
{
|
|
||||||
_k_alert_list_start = .;
|
|
||||||
KEEP(*(SORT_BY_NAME("._k_alert.static.*")))
|
|
||||||
_k_alert_list_end = .;
|
|
||||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
|
||||||
|
|
||||||
SECTION_DATA_PROLOGUE(_k_queue_area, (OPTIONAL), SUBALIGN(4))
|
SECTION_DATA_PROLOGUE(_k_queue_area, (OPTIONAL), SUBALIGN(4))
|
||||||
{
|
{
|
||||||
_k_queue_list_start = .;
|
_k_queue_list_start = .;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# kernel is a normal CMake library and not a zephyr_library because it
|
# kernel is a normal CMake library and not a zephyr_library because it
|
||||||
# should not be --whole-archive'd
|
# should not be --whole-archive'd
|
||||||
add_library(kernel
|
add_library(kernel
|
||||||
alert.c
|
|
||||||
device.c
|
device.c
|
||||||
errno.c
|
errno.c
|
||||||
idle.c
|
idle.c
|
||||||
|
|
110
kernel/alert.c
110
kernel/alert.c
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Wind River Systems, Inc.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief kernel alerts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <kernel.h>
|
|
||||||
#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[];
|
|
||||||
|
|
||||||
#ifdef CONFIG_OBJECT_TRACING
|
|
||||||
|
|
||||||
struct k_alert *_trace_list_k_alert;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
_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
|
|
|
@ -17,7 +17,6 @@ from elf_helper import ElfHelper, kobject_to_enum
|
||||||
# available in all configurations.
|
# available in all configurations.
|
||||||
|
|
||||||
kobjects = {
|
kobjects = {
|
||||||
"k_alert": None,
|
|
||||||
"k_mem_slab": None,
|
"k_mem_slab": None,
|
||||||
"k_msgq": None,
|
"k_msgq": None,
|
||||||
"k_mutex": None,
|
"k_mutex": None,
|
||||||
|
|
|
@ -671,7 +671,7 @@ class SizeCalculator:
|
||||||
"_k_memory_pool", "exceptions", "initshell",
|
"_k_memory_pool", "exceptions", "initshell",
|
||||||
"_static_thread_area", "_k_timer_area",
|
"_static_thread_area", "_k_timer_area",
|
||||||
"_k_mem_slab_area", "_k_mem_pool_area", "sw_isr_table",
|
"_k_mem_slab_area", "_k_mem_pool_area", "sw_isr_table",
|
||||||
"_k_sem_area", "_k_mutex_area", "_k_alert_area",
|
"_k_sem_area", "_k_mutex_area",
|
||||||
"_k_fifo_area", "_k_lifo_area", "_k_stack_area",
|
"_k_fifo_area", "_k_lifo_area", "_k_stack_area",
|
||||||
"_k_msgq_area", "_k_mbox_area", "_k_pipe_area",
|
"_k_msgq_area", "_k_mbox_area", "_k_pipe_area",
|
||||||
"net_if", "net_if_dev", "net_stack", "net_l2_data",
|
"net_if", "net_if_dev", "net_stack", "net_l2_data",
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
/* event_b.c */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1997-2014 Wind River Systems, Inc.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "master.h"
|
|
||||||
|
|
||||||
#ifdef EVENT_BENCH
|
|
||||||
|
|
||||||
/* #define EVENT_CHECK */
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
static const char event_signal_err[] = "----------- Error signalling event.\n";
|
|
||||||
static const char event_test_err[] = "----------- Error testing event.\n";
|
|
||||||
static const char event_handler_err[] = "----------- Error in event handler\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* global Event value */
|
|
||||||
volatile int nevent_value;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function prototypes.
|
|
||||||
*/
|
|
||||||
int example_handler (struct k_alert *alert);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function declarations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief Event signal speed test
|
|
||||||
*
|
|
||||||
* @return N/A
|
|
||||||
*/
|
|
||||||
void event_test(void)
|
|
||||||
{
|
|
||||||
int nreturn = 0;
|
|
||||||
int ncounter;
|
|
||||||
u32_t et; /* elapsed time */
|
|
||||||
|
|
||||||
PRINT_STRING(dashline, output_file);
|
|
||||||
et = BENCH_START();
|
|
||||||
for (ncounter = 0; ncounter < NR_OF_EVENT_RUNS; ncounter++) {
|
|
||||||
k_alert_send(&TEST_EVENT);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_signal_err, output_file);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
}
|
|
||||||
et = TIME_STAMP_DELTA_GET(et);
|
|
||||||
check_result();
|
|
||||||
|
|
||||||
PRINT_F(output_file, FORMAT, "Signal enabled event",
|
|
||||||
SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_EVENT_RUNS));
|
|
||||||
|
|
||||||
et = BENCH_START();
|
|
||||||
for (ncounter = 0; ncounter < NR_OF_EVENT_RUNS; ncounter++) {
|
|
||||||
k_alert_send(&TEST_EVENT);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_signal_err, output_file);
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
k_alert_recv(&TEST_EVENT, K_NO_WAIT);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_test_err, output_file);
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
}
|
|
||||||
et = TIME_STAMP_DELTA_GET(et);
|
|
||||||
check_result();
|
|
||||||
|
|
||||||
PRINT_F(output_file, FORMAT, "Signal event & Test event",
|
|
||||||
SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_EVENT_RUNS));
|
|
||||||
|
|
||||||
et = BENCH_START();
|
|
||||||
for (ncounter = 0; ncounter < NR_OF_EVENT_RUNS; ncounter++) {
|
|
||||||
k_alert_send(&TEST_EVENT);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_signal_err, output_file);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
k_alert_recv(&TEST_EVENT, K_FOREVER);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_test_err, output_file);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
}
|
|
||||||
et = TIME_STAMP_DELTA_GET(et);
|
|
||||||
check_result();
|
|
||||||
|
|
||||||
PRINT_F(output_file, FORMAT, "Signal event & TestW event",
|
|
||||||
SYS_CLOCK_HW_CYCLES_TO_NS_AVG(et, NR_OF_EVENT_RUNS));
|
|
||||||
|
|
||||||
PRINT_STRING("| Signal event with installed handler"
|
|
||||||
" |\n", output_file);
|
|
||||||
TEST_EVENT.handler = example_handler;
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_F(output_file,
|
|
||||||
"-------- Error installing event handler.\n");
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ncounter = 0; ncounter < NR_OF_EVENT_RUNS; ncounter++) {
|
|
||||||
k_alert_send(&TEST_EVENT);
|
|
||||||
#ifdef EVENT_CHECK
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_STRING(event_signal_err, output_file);
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
if (nevent_value != TEST_EVENT.send_count + 1) {
|
|
||||||
PRINT_STRING(event_handler_err, output_file);
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
#endif /* EVENT_CHECK */
|
|
||||||
nevent_value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_EVENT.handler = NULL;
|
|
||||||
if (nreturn != 0) {
|
|
||||||
PRINT_F(output_file, "Error removing event handler.\n");
|
|
||||||
k_sleep(1);
|
|
||||||
return; /* error */
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT_STRING("| Handler responds OK"
|
|
||||||
" |\n",
|
|
||||||
output_file);
|
|
||||||
|
|
||||||
return; /* success */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief Event handler for the tests
|
|
||||||
*
|
|
||||||
* The event handler for the test. Sets up nEventValue global variable.
|
|
||||||
* This variable is used in the main test.
|
|
||||||
*
|
|
||||||
* @return 1
|
|
||||||
*/
|
|
||||||
int example_handler (struct k_alert *alert)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(alert);
|
|
||||||
nevent_value = alert->send_count + 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* EVENT_BENCH */
|
|
|
@ -63,8 +63,6 @@ K_PIPE_DEFINE(PIPE_BIGBUFF, 4096, 4);
|
||||||
|
|
||||||
K_MEM_POOL_DEFINE(DEMOPOOL, 16, 16, 1, 4);
|
K_MEM_POOL_DEFINE(DEMOPOOL, 16, 16, 1, 4);
|
||||||
|
|
||||||
K_ALERT_DEFINE(TEST_EVENT, NULL, 1);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -138,7 +136,6 @@ void main(void)
|
||||||
mutex_test();
|
mutex_test();
|
||||||
memorymap_test();
|
memorymap_test();
|
||||||
mempool_test();
|
mempool_test();
|
||||||
event_test();
|
|
||||||
mailbox_test();
|
mailbox_test();
|
||||||
pipe_test();
|
pipe_test();
|
||||||
PRINT_STRING("| END OF TESTS "
|
PRINT_STRING("| END OF TESTS "
|
||||||
|
|
|
@ -122,12 +122,6 @@ extern void pipe_test(void);
|
||||||
#define pipe_test dummy_test
|
#define pipe_test dummy_test
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVENT_BENCH
|
|
||||||
extern void event_test(void);
|
|
||||||
#else
|
|
||||||
#define event_test dummy_test
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* kernel objects needed for benchmarking */
|
/* kernel objects needed for benchmarking */
|
||||||
extern struct k_mutex DEMO_MUTEX;
|
extern struct k_mutex DEMO_MUTEX;
|
||||||
|
|
||||||
|
@ -153,8 +147,6 @@ extern struct k_pipe PIPE_BIGBUFF;
|
||||||
|
|
||||||
extern struct k_mem_slab MAP1;
|
extern struct k_mem_slab MAP1;
|
||||||
|
|
||||||
extern struct k_alert TEST_EVENT;
|
|
||||||
|
|
||||||
extern struct k_mem_pool DEMOPOOL;
|
extern struct k_mem_pool DEMOPOOL;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,6 @@ static pfunc func_array[] = {
|
||||||
(pfunc)k_mem_slab_num_free_get,
|
(pfunc)k_mem_slab_num_free_get,
|
||||||
|
|
||||||
#ifdef TEST_max
|
#ifdef TEST_max
|
||||||
/* alerts */
|
|
||||||
(pfunc)k_alert_init,
|
|
||||||
(pfunc)k_alert_send,
|
|
||||||
(pfunc)k_alert_recv,
|
|
||||||
|
|
||||||
/* message queues */
|
/* message queues */
|
||||||
(pfunc)k_msgq_init,
|
(pfunc)k_msgq_init,
|
||||||
(pfunc)k_msgq_put,
|
(pfunc)k_msgq_put,
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.13.1)
|
|
||||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
|
||||||
project(alert_api)
|
|
||||||
|
|
||||||
FILE(GLOB app_sources src/*.c)
|
|
||||||
target_sources(app PRIVATE ${app_sources})
|
|
|
@ -1,2 +0,0 @@
|
||||||
CONFIG_ZTEST=y
|
|
||||||
CONFIG_IRQ_OFFLOAD=y
|
|
|
@ -1,524 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ztest.h>
|
|
||||||
#include <irq_offload.h>
|
|
||||||
|
|
||||||
#define TIMEOUT 100
|
|
||||||
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
|
||||||
#define PENDING_MAX 2
|
|
||||||
#define SEM_INITIAL 0
|
|
||||||
#define SEM_LIMIT 1
|
|
||||||
|
|
||||||
K_SEM_DEFINE(sync_sema, SEM_INITIAL, SEM_LIMIT);
|
|
||||||
|
|
||||||
static int alert_handler0(struct k_alert *);
|
|
||||||
static int alert_handler1(struct k_alert *);
|
|
||||||
|
|
||||||
/**TESTPOINT: init via K_ALERT_DEFINE*/
|
|
||||||
K_ALERT_DEFINE(kalert_pending, alert_handler1, PENDING_MAX);
|
|
||||||
K_ALERT_DEFINE(kalert_consumed, alert_handler0, PENDING_MAX);
|
|
||||||
|
|
||||||
enum handle_type {
|
|
||||||
HANDLER_IGNORE,
|
|
||||||
HANDLER_DEFAULT,
|
|
||||||
HANDLER_0,
|
|
||||||
HANDLER_1
|
|
||||||
};
|
|
||||||
|
|
||||||
static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE);
|
|
||||||
static K_THREAD_STACK_DEFINE(sync_tstack, STACK_SIZE);
|
|
||||||
__kernel struct k_thread tdata;
|
|
||||||
__kernel struct k_thread sync_tdata;
|
|
||||||
__kernel struct k_alert thread_alerts[4];
|
|
||||||
static struct k_alert *palert;
|
|
||||||
static enum handle_type htype;
|
|
||||||
static volatile u32_t handler_executed;
|
|
||||||
static volatile u32_t handler_val;
|
|
||||||
|
|
||||||
|
|
||||||
/*handlers*/
|
|
||||||
static int alert_handler0(struct k_alert *alt)
|
|
||||||
{
|
|
||||||
handler_executed++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int alert_handler1(struct k_alert *alt)
|
|
||||||
{
|
|
||||||
handler_executed++;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void alert_send(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert send*/
|
|
||||||
for (int i = 0; i < PENDING_MAX; i++) {
|
|
||||||
k_alert_send(palert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void alert_recv(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (htype) {
|
|
||||||
case HANDLER_0:
|
|
||||||
zassert_equal(handler_executed, PENDING_MAX, NULL);
|
|
||||||
/* Fall through */
|
|
||||||
case HANDLER_IGNORE:
|
|
||||||
ret = k_alert_recv(palert, TIMEOUT);
|
|
||||||
zassert_equal(ret, -EAGAIN, NULL);
|
|
||||||
break;
|
|
||||||
case HANDLER_1:
|
|
||||||
zassert_equal(handler_executed, PENDING_MAX, NULL);
|
|
||||||
/* Fall through */
|
|
||||||
case HANDLER_DEFAULT:
|
|
||||||
for (int i = 0; i < PENDING_MAX; i++) {
|
|
||||||
/**TESTPOINT: alert recv*/
|
|
||||||
ret = k_alert_recv(palert, K_NO_WAIT);
|
|
||||||
zassert_false(ret, NULL);
|
|
||||||
}
|
|
||||||
/**TESTPOINT: alert recv -EAGAIN*/
|
|
||||||
ret = k_alert_recv(palert, TIMEOUT);
|
|
||||||
zassert_equal(ret, -EAGAIN, NULL);
|
|
||||||
/**TESTPOINT: alert recv -EBUSY*/
|
|
||||||
ret = k_alert_recv(palert, K_NO_WAIT);
|
|
||||||
zassert_equal(ret, -EBUSY, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void thread_entry(void *p1, void *p2, void *p3)
|
|
||||||
{
|
|
||||||
alert_recv();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void thread_alert(void)
|
|
||||||
{
|
|
||||||
handler_executed = 0U;
|
|
||||||
/**TESTPOINT: thread-thread sync via alert*/
|
|
||||||
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
|
|
||||||
thread_entry, NULL, NULL, NULL,
|
|
||||||
K_PRIO_PREEMPT(0),
|
|
||||||
K_USER | K_INHERIT_PERMS,
|
|
||||||
0);
|
|
||||||
alert_send();
|
|
||||||
k_sleep(TIMEOUT);
|
|
||||||
k_thread_abort(tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tisr_entry(void *p)
|
|
||||||
{
|
|
||||||
alert_send();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sync_entry(void *p)
|
|
||||||
{
|
|
||||||
k_alert_send(palert);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void isr_alert(void)
|
|
||||||
{
|
|
||||||
handler_executed = 0U;
|
|
||||||
/**TESTPOINT: thread-isr sync via alert*/
|
|
||||||
irq_offload(tisr_entry, NULL);
|
|
||||||
k_sleep(TIMEOUT);
|
|
||||||
alert_recv();
|
|
||||||
}
|
|
||||||
|
|
||||||
int event_handler(struct k_alert *alt)
|
|
||||||
{
|
|
||||||
return handler_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tests for the Alert kernel object
|
|
||||||
* @defgroup kernel_alert_tests Alerts
|
|
||||||
* @ingroup all_tests
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread alert default
|
|
||||||
*
|
|
||||||
* Checks k_alert_init(), k_alert_send(), k_alert_recv() Kernel APIs.
|
|
||||||
*
|
|
||||||
* Initializes an alert and creates a thread that signals an alert with
|
|
||||||
* k_alert_send() and then calls k_alert_recv() with K_NO_WAIT to receive the
|
|
||||||
* alerts. Checks if k_alert_recv() returns appropriate error values when
|
|
||||||
* alerts are not received.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_default(void)
|
|
||||||
{
|
|
||||||
palert = &thread_alerts[HANDLER_DEFAULT];
|
|
||||||
htype = HANDLER_DEFAULT;
|
|
||||||
thread_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread alert ignore
|
|
||||||
*
|
|
||||||
* Checks k_alert_init(), k_alert_send(), k_alert_recv() Kernel APIs - creates
|
|
||||||
* a thread that signals an alert using k_alert_send() and then calls
|
|
||||||
* k_alert_recv() with TIMEOUT of 100ms which is the waiting period for
|
|
||||||
* receiving the alert.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_ignore(void)
|
|
||||||
{
|
|
||||||
palert = &thread_alerts[HANDLER_IGNORE];
|
|
||||||
htype = HANDLER_IGNORE;
|
|
||||||
thread_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread alert consumed
|
|
||||||
*
|
|
||||||
* Checks k_alert_init(), k_alert_send(), k_alert_recv() Kernel APIs.
|
|
||||||
*
|
|
||||||
* Creates a thread that signals an alert using k_alert_send(). Now
|
|
||||||
* k_alert_send() for this case is initialized with an address of the handler
|
|
||||||
* function, which increases handler_executed count each time it is called.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_consumed(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler return 0*/
|
|
||||||
palert = &thread_alerts[HANDLER_0];
|
|
||||||
htype = HANDLER_0;
|
|
||||||
thread_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread alert pending
|
|
||||||
*
|
|
||||||
* Checks k_alert_init(), k_alert_send(), k_alert_recv() Kernel APIs
|
|
||||||
*
|
|
||||||
* Creates a thread that signals an alert using k_alert_send().
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_pending(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler return 1*/
|
|
||||||
palert = &thread_alerts[HANDLER_1];
|
|
||||||
htype = HANDLER_1;
|
|
||||||
thread_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test default isr alert
|
|
||||||
*
|
|
||||||
* Similar to test_thread_alert_default(), but verifies kernel objects and
|
|
||||||
* APIs work correctly in interrupt context with the help of irq_offload()
|
|
||||||
* function.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_isr_alert_default(void)
|
|
||||||
{
|
|
||||||
struct k_alert alert;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, K_ALERT_DEFAULT, PENDING_MAX);
|
|
||||||
|
|
||||||
/**TESTPOINT: alert handler default*/
|
|
||||||
palert = &alert;
|
|
||||||
htype = HANDLER_DEFAULT;
|
|
||||||
isr_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test isr alert ignore
|
|
||||||
*
|
|
||||||
* Similar to test_thread_alert_ignore(), but verifies kernel objects and
|
|
||||||
* APIs work correctly in interrupt context with the help of irq_offload()
|
|
||||||
* function.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_isr_alert_ignore(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler ignore*/
|
|
||||||
struct k_alert alert;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, K_ALERT_IGNORE, PENDING_MAX);
|
|
||||||
palert = &alert;
|
|
||||||
htype = HANDLER_IGNORE;
|
|
||||||
isr_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test isr alert consumed
|
|
||||||
*
|
|
||||||
* Similar to test_thread_alert_consumed, but verifies kernel objects
|
|
||||||
* and APIs work correctly in interrupt context with the help of irq_offload()
|
|
||||||
* function.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_isr_alert_consumed(void)
|
|
||||||
{
|
|
||||||
struct k_alert alert;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, alert_handler0, PENDING_MAX);
|
|
||||||
|
|
||||||
/**TESTPOINT: alert handler return 0*/
|
|
||||||
palert = &alert;
|
|
||||||
htype = HANDLER_0;
|
|
||||||
isr_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test isr alert pending
|
|
||||||
*
|
|
||||||
* Similar to test_thread_alert_pending(), but verifies kernel objects and
|
|
||||||
* APIs work correctly in interrupt context with the help of irq_offload()
|
|
||||||
* function.
|
|
||||||
*
|
|
||||||
* @see k_alert_init(), k_alert_send(), k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_isr_alert_pending(void)
|
|
||||||
{
|
|
||||||
struct k_alert alert;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, alert_handler1, PENDING_MAX);
|
|
||||||
|
|
||||||
/**TESTPOINT: alert handler return 0*/
|
|
||||||
palert = &alert;
|
|
||||||
htype = HANDLER_1;
|
|
||||||
isr_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread kinit alert
|
|
||||||
*
|
|
||||||
* Tests consumed and pending thread alert cases (reference line numbers 4 and
|
|
||||||
* 5), but handles case where alert has been defined via #K_ALERT_DEFINE(x) and not
|
|
||||||
* k_alert_init()
|
|
||||||
*
|
|
||||||
* @see #K_ALERT_DEFINE(x)
|
|
||||||
*/
|
|
||||||
void test_thread_kinit_alert(void)
|
|
||||||
{
|
|
||||||
palert = &kalert_consumed;
|
|
||||||
htype = HANDLER_0;
|
|
||||||
thread_alert();
|
|
||||||
palert = &kalert_pending;
|
|
||||||
htype = HANDLER_1;
|
|
||||||
thread_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test isr kinit alert
|
|
||||||
*
|
|
||||||
* Checks consumed and pending isr alert cases but alert has been defined via
|
|
||||||
* #K_ALERT_DEFINE(x) and not k_alert_init()
|
|
||||||
*
|
|
||||||
* @see #K_ALERT_DEFINE(x)
|
|
||||||
*/
|
|
||||||
void test_isr_kinit_alert(void)
|
|
||||||
{
|
|
||||||
palert = &kalert_consumed;
|
|
||||||
htype = HANDLER_0;
|
|
||||||
isr_alert();
|
|
||||||
palert = &kalert_pending;
|
|
||||||
htype = HANDLER_1;
|
|
||||||
isr_alert();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test alert_recv(timeout)
|
|
||||||
*
|
|
||||||
* This test checks k_alert_recv(timeout) against the following cases:
|
|
||||||
* 1. The current task times out while waiting for the event.
|
|
||||||
* 2. There is already an event waiting (signaled from a task).
|
|
||||||
* 3. The current task must wait on the event until it is signaled
|
|
||||||
* from either another task or an ISR.
|
|
||||||
*
|
|
||||||
* @see k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_timeout(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler ignore*/
|
|
||||||
struct k_alert alert;
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, K_ALERT_DEFAULT, PENDING_MAX);
|
|
||||||
|
|
||||||
palert = &alert;
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, TIMEOUT);
|
|
||||||
|
|
||||||
zassert_equal(ret, -EAGAIN, NULL);
|
|
||||||
|
|
||||||
k_alert_send(&alert);
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, TIMEOUT);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
|
|
||||||
k_sem_give(&sync_sema);
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
ret = k_alert_recv(&alert, TIMEOUT);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test k_alert_recv() against different cases
|
|
||||||
*
|
|
||||||
* This test checks k_alert_recv(K_FOREVER) against
|
|
||||||
* the following cases:
|
|
||||||
* 1. There is already an event waiting (signaled from a task and ISR).
|
|
||||||
* 2. The current task must wait on the event until it is signaled
|
|
||||||
* from either another task or an ISR.
|
|
||||||
*
|
|
||||||
* @see k_alert_recv()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_wait(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler ignore*/
|
|
||||||
struct k_alert alert;
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, K_ALERT_DEFAULT, PENDING_MAX);
|
|
||||||
|
|
||||||
palert = &alert;
|
|
||||||
|
|
||||||
k_alert_send(&alert);
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, K_FOREVER);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
|
|
||||||
irq_offload(sync_entry, NULL);
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, K_FOREVER);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
|
|
||||||
k_sem_give(&sync_sema);
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
ret = k_alert_recv(&alert, K_FOREVER);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test thread alert handler
|
|
||||||
*
|
|
||||||
* This test checks that the event handler is set up properly when
|
|
||||||
* k_alert_init() is called with an event handler. It shows that event
|
|
||||||
* handlers are tied to the specified event and that the return value from the
|
|
||||||
* handler affects whether the event wakes a task waiting upon that event.
|
|
||||||
*
|
|
||||||
* @see k_alert_init()
|
|
||||||
*/
|
|
||||||
void test_thread_alert_handler(void)
|
|
||||||
{
|
|
||||||
/**TESTPOINT: alert handler ignore*/
|
|
||||||
struct k_alert alert;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/**TESTPOINT: init via k_alert_init*/
|
|
||||||
k_alert_init(&alert, event_handler, PENDING_MAX);
|
|
||||||
|
|
||||||
palert = &alert;
|
|
||||||
|
|
||||||
k_sem_give(&sync_sema);
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, TIMEOUT);
|
|
||||||
|
|
||||||
zassert_equal(ret, -EAGAIN, NULL);
|
|
||||||
|
|
||||||
k_sem_give(&sync_sema);
|
|
||||||
|
|
||||||
ret = k_alert_recv(&alert, TIMEOUT);
|
|
||||||
|
|
||||||
zassert_equal(ret, 0, NULL);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal various events to a waiting task
|
|
||||||
*/
|
|
||||||
void signal_task(void *p1, void *p2, void *p3)
|
|
||||||
{
|
|
||||||
k_sem_init(&sync_sema, 0, 1);
|
|
||||||
|
|
||||||
k_sem_take(&sync_sema, K_FOREVER);
|
|
||||||
k_alert_send(palert);
|
|
||||||
irq_offload(sync_entry, NULL);
|
|
||||||
|
|
||||||
k_sem_take(&sync_sema, K_FOREVER);
|
|
||||||
k_alert_send(palert);
|
|
||||||
irq_offload(sync_entry, NULL);
|
|
||||||
|
|
||||||
k_sem_take(&sync_sema, K_FOREVER);
|
|
||||||
handler_val = 0U;
|
|
||||||
k_alert_send(palert);
|
|
||||||
|
|
||||||
k_sem_take(&sync_sema, K_FOREVER);
|
|
||||||
handler_val = 1U;
|
|
||||||
k_alert_send(palert);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*test case main entry*/
|
|
||||||
void test_main(void)
|
|
||||||
{
|
|
||||||
k_thread_access_grant(k_current_get(), &kalert_pending,
|
|
||||||
&kalert_consumed, &tdata, &tstack,
|
|
||||||
&thread_alerts[HANDLER_DEFAULT],
|
|
||||||
&thread_alerts[HANDLER_IGNORE],
|
|
||||||
&thread_alerts[HANDLER_0],
|
|
||||||
&thread_alerts[HANDLER_1]);
|
|
||||||
|
|
||||||
k_alert_init(&thread_alerts[HANDLER_DEFAULT], K_ALERT_DEFAULT,
|
|
||||||
PENDING_MAX);
|
|
||||||
k_alert_init(&thread_alerts[HANDLER_IGNORE], K_ALERT_IGNORE,
|
|
||||||
PENDING_MAX);
|
|
||||||
k_alert_init(&thread_alerts[HANDLER_0], alert_handler0, PENDING_MAX);
|
|
||||||
k_alert_init(&thread_alerts[HANDLER_1], alert_handler1, PENDING_MAX);
|
|
||||||
|
|
||||||
/**TESTPOINT: thread-thread sync via alert*/
|
|
||||||
k_thread_create(&sync_tdata, sync_tstack, STACK_SIZE,
|
|
||||||
signal_task, NULL, NULL, NULL,
|
|
||||||
K_PRIO_PREEMPT(0), 0, 0);
|
|
||||||
|
|
||||||
ztest_test_suite(alert_api,
|
|
||||||
ztest_unit_test(test_thread_alert_timeout),
|
|
||||||
ztest_unit_test(test_thread_alert_wait),
|
|
||||||
ztest_unit_test(test_thread_alert_handler),
|
|
||||||
ztest_user_unit_test(test_thread_alert_default),
|
|
||||||
ztest_user_unit_test(test_thread_alert_ignore),
|
|
||||||
ztest_user_unit_test(test_thread_alert_consumed),
|
|
||||||
ztest_user_unit_test(test_thread_alert_pending),
|
|
||||||
ztest_unit_test(test_isr_alert_default),
|
|
||||||
ztest_unit_test(test_isr_alert_ignore),
|
|
||||||
ztest_unit_test(test_isr_alert_consumed),
|
|
||||||
ztest_unit_test(test_isr_alert_pending),
|
|
||||||
ztest_user_unit_test(test_thread_kinit_alert),
|
|
||||||
ztest_unit_test(test_isr_kinit_alert));
|
|
||||||
ztest_run_test_suite(alert_api);
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
tests:
|
|
||||||
kernel.alert:
|
|
||||||
tags: kernel userspace
|
|
|
@ -13,7 +13,6 @@ enum obj_name {
|
||||||
MEM_SLAB,
|
MEM_SLAB,
|
||||||
SEM,
|
SEM,
|
||||||
MUTEX,
|
MUTEX,
|
||||||
ALERT,
|
|
||||||
STACK,
|
STACK,
|
||||||
MSGQ,
|
MSGQ,
|
||||||
MBOX,
|
MBOX,
|
||||||
|
@ -30,16 +29,10 @@ static inline void stop_dummy_fn(struct k_timer *timer)
|
||||||
ARG_UNUSED(timer);
|
ARG_UNUSED(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void alert_handler_dummy(struct k_alert *alert)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(alert);
|
|
||||||
}
|
|
||||||
|
|
||||||
K_TIMER_DEFINE(ktimer, expiry_dummy_fn, stop_dummy_fn);
|
K_TIMER_DEFINE(ktimer, expiry_dummy_fn, stop_dummy_fn);
|
||||||
K_MEM_SLAB_DEFINE(kmslab, 4, 2, 4);
|
K_MEM_SLAB_DEFINE(kmslab, 4, 2, 4);
|
||||||
K_SEM_DEFINE(ksema, 0, 1);
|
K_SEM_DEFINE(ksema, 0, 1);
|
||||||
K_MUTEX_DEFINE(kmutex);
|
K_MUTEX_DEFINE(kmutex);
|
||||||
K_ALERT_DEFINE(kalert, alert_handler_dummy, 1);
|
|
||||||
K_STACK_DEFINE(kstack, 512);
|
K_STACK_DEFINE(kstack, 512);
|
||||||
K_MSGQ_DEFINE(kmsgq, 4, 2, 4);
|
K_MSGQ_DEFINE(kmsgq, 4, 2, 4);
|
||||||
K_MBOX_DEFINE(kmbox);
|
K_MBOX_DEFINE(kmbox);
|
||||||
|
@ -50,7 +43,6 @@ static struct k_timer timer;
|
||||||
static struct k_mem_slab mslab;
|
static struct k_mem_slab mslab;
|
||||||
static struct k_sem sema;
|
static struct k_sem sema;
|
||||||
static struct k_mutex mutex;
|
static struct k_mutex mutex;
|
||||||
static struct k_alert alert;
|
|
||||||
static struct k_stack stack;
|
static struct k_stack stack;
|
||||||
static struct k_msgq msgq;
|
static struct k_msgq msgq;
|
||||||
static struct k_mbox mbox;
|
static struct k_mbox mbox;
|
||||||
|
@ -142,23 +134,6 @@ static void get_obj_count(int obj_type)
|
||||||
}
|
}
|
||||||
zassert_equal(obj_found, 2, "Didn't find mutex objects");
|
zassert_equal(obj_found, 2, "Didn't find mutex objects");
|
||||||
break;
|
break;
|
||||||
case ALERT:
|
|
||||||
k_alert_init(&alert, K_ALERT_IGNORE, 1);
|
|
||||||
|
|
||||||
obj_list = SYS_TRACING_HEAD(struct k_alert, k_alert);
|
|
||||||
while (obj_list != NULL) {
|
|
||||||
if (obj_list == &kalert || obj_list == &alert) {
|
|
||||||
obj_found++;
|
|
||||||
if (obj_found == 2) {
|
|
||||||
TC_PRINT("Found alert objects\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj_list = SYS_TRACING_NEXT(struct k_alert, k_alert,
|
|
||||||
obj_list);
|
|
||||||
}
|
|
||||||
zassert_equal(obj_found, 2, "Didn't find alert objects");
|
|
||||||
break;
|
|
||||||
case STACK:
|
case STACK:
|
||||||
k_stack_init(&stack, sdata, NUM_BLOCKS);
|
k_stack_init(&stack, sdata, NUM_BLOCKS);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue