doc: Kernel event logger documentation
Add the kernel event logger documentation where the user can find how to use this mechanism and which event logging points are available currently. Change-Id: I6d86c7b79c6b4a56a9e3514b6c4933a35e0c782f Signed-off-by: Yonattan Louise <yonattan.a.louise.mendoza@intel.com>
This commit is contained in:
parent
3cc5b7b15e
commit
6221ef066e
2 changed files with 231 additions and 0 deletions
|
@ -16,3 +16,4 @@ applications and nanokernel applications.
|
|||
nanokernel_synchronization
|
||||
nanokernel_data
|
||||
nanokernel_interrupts
|
||||
nanokernel_kernel_event_logger
|
||||
|
|
230
doc/kernel/nanokernel/nanokernel_kernel_event_logger.rst
Normal file
230
doc/kernel/nanokernel/nanokernel_kernel_event_logger.rst
Normal file
|
@ -0,0 +1,230 @@
|
|||
.. _nanokernel_event_logger:
|
||||
|
||||
Kernel Event Logger
|
||||
###################
|
||||
|
||||
Definition
|
||||
**********
|
||||
|
||||
The kernel event logger is a standardized mechanism to record events within the Kernel while
|
||||
providing a single interface for the user to collect the data. This mechanism is currently used
|
||||
to log the following events:
|
||||
|
||||
* Sleep events (entering and exiting low power conditions).
|
||||
* Context switch events.
|
||||
* Interrupt events.
|
||||
|
||||
Kernel Event Logger Configuration
|
||||
*********************************
|
||||
|
||||
Kconfig provides the ability to enable and disable the collection of events and to configure the
|
||||
size of the buffer used by the event logger.
|
||||
|
||||
These options can be found in the following path :file:`kernel/Kconfig`.
|
||||
|
||||
General kernel event logger configuration:
|
||||
|
||||
* :option:`KERNEL_EVENT_LOGGER_BUFFER_SIZE`
|
||||
|
||||
Default size: 128 words, 32-bit length.
|
||||
|
||||
Profiling points configuration:
|
||||
|
||||
* :option:`KERNEL_EVENT_INTERRUPT`
|
||||
|
||||
Enables recording of interrupt-driven events by providing timestamp information.
|
||||
|
||||
* :option:`KERNEL_EVENT_SLEEP`
|
||||
|
||||
Enables recording of sleep events:
|
||||
|
||||
* Timestamp when the CPU went to sleep mode.
|
||||
* Timestamp when the CPU woke up.
|
||||
* The interrupt Id that woke the CPU up.
|
||||
|
||||
* :option:`KERNEL_EVENT_CONTEXT`
|
||||
|
||||
Enables recording of context-switching events. Details include:
|
||||
|
||||
* Which thread is leaving the CPU.
|
||||
* Timestamp when the event has occurred.
|
||||
|
||||
Adding a Kernel Event Logging Point
|
||||
***********************************
|
||||
|
||||
Custom trace points can be added with the following API:
|
||||
|
||||
* :cpp:func:`sys_k_event_logger_put()`
|
||||
|
||||
Adds the profile of a new event with custom data.
|
||||
|
||||
* :cpp:func:`sys_k_event_logger_put_timed()`
|
||||
|
||||
Adds timestamped profile of a new event.
|
||||
|
||||
.. important::
|
||||
|
||||
The data must be in 32-bit sized blocks.
|
||||
|
||||
Retrieving Kernel Event Data
|
||||
****************************
|
||||
|
||||
Applications are required to implement a fiber for accessing the recorded event messages
|
||||
in both the nanokernel and microkernel systems. Developers can use the provided API to
|
||||
retrieve the data, or may write their own routines using the ring buffer provided by the
|
||||
event logger.
|
||||
|
||||
The API functions provided are:
|
||||
|
||||
* :cpp:func:`sys_k_event_logger_get()`
|
||||
* :cpp:func:`sys_k_event_logger_get_wait()`
|
||||
* :cpp:func:`sys_k_event_logger_get_wait_timeout()`
|
||||
|
||||
The above functions specify various ways to retrieve a event message and to copy it to
|
||||
the provided buffer. When the buffer size is smaller than the message, the function will
|
||||
return an error. All three functions retrieve messages via a FIFO method. The :literal:`wait`
|
||||
and :literal:`wait_timeout` functions allow the caller to pend until a new message is
|
||||
logged, or until the timeout expires.
|
||||
|
||||
Message Formats
|
||||
***************
|
||||
|
||||
Interrupt-driven Event Messaging
|
||||
--------------------------------
|
||||
|
||||
The data of the interrupt-driven event message comes in two block of 32 bits:
|
||||
|
||||
* The first block contains the timestamp occurrence of the interrupt event.
|
||||
* The second block contains the Id of the interrupt.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
uint32_t data[2];
|
||||
data[0] = timestamp_event;
|
||||
data[1] = interrupt_id;
|
||||
|
||||
Context-switch Event Messaging
|
||||
------------------------------
|
||||
|
||||
The data of the context-switch event message comes in two block of 32 bits:
|
||||
|
||||
* The first block contains the timestamp occurrence of the context-switch event.
|
||||
* The second block contains the thread id of the context involved.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
uint32_t data[2];
|
||||
data[0] = timestamp_event;
|
||||
data[1] = context_id;
|
||||
|
||||
Sleep Event Messaging
|
||||
---------------------
|
||||
|
||||
The data of the sleep event message comes in three block of 32 bits:
|
||||
|
||||
* The first block contains the timestamp when the CPU went to sleep mode.
|
||||
* The second block contains the timestamp when the CPU woke up.
|
||||
* The third block contains the interrupt Id that woke the CPU up.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
uint32_t data[3];
|
||||
data[0] = timestamp_went_sleep;
|
||||
data[1] = timestamp woke_up.
|
||||
data[2] = interrupt_id.
|
||||
|
||||
Example: Retrieving Profiling Messages
|
||||
======================================
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
uint32_t data[3];
|
||||
uint8_t data_length = SIZE32_OF(data);
|
||||
uint8_t dropped_count;
|
||||
|
||||
while(1) {
|
||||
/* collect the data */
|
||||
res = sys_k_event_logger_get_wait(&event_id, &dropped_count, data,
|
||||
&data_length);
|
||||
|
||||
if (dropped_count > 0) {
|
||||
/* process the message dropped count */
|
||||
}
|
||||
|
||||
if (res > 0) {
|
||||
/* process the data */
|
||||
switch (event_id) {
|
||||
case KERNEL_EVENT_CONTEXT_SWITCH_EVENT_ID:
|
||||
/* ... Process the context switch event data ... */
|
||||
break;
|
||||
case KERNEL_EVENT_INTERRUPT_EVENT_ID:
|
||||
/* ... Process the interrupt event data ... */
|
||||
break;
|
||||
case KERNEL_EVENT_SLEEP_EVENT_ID:
|
||||
/* ... Process the data for a sleep event ... */
|
||||
break;
|
||||
default:
|
||||
printf("unrecognized event id %d\n", event_id);
|
||||
}
|
||||
} else {
|
||||
if (res == -EMSGSIZE) {
|
||||
/* ERROR - The buffer provided to collect the
|
||||
* profiling events is too small.
|
||||
*/
|
||||
} else if (ret == -EAGAIN) {
|
||||
/* There is no message available in the buffer */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
To see an example that shows how to collect the kernel event data, check the sample
|
||||
project: :file:`samples/microkernel/apps/kernel_event_logger_sample`.
|
||||
|
||||
Example: Adding a Kernel Event Logging Point
|
||||
============================================
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
uint32_t data[2];
|
||||
|
||||
data[0] = custom_data_1;
|
||||
data[1] = custom_data_2;
|
||||
|
||||
sys_k_event_logger_put(KERNEL_EVENT_LOGGER_CUSTOM_ID, data, ARRAY_SIZE(data));
|
||||
|
||||
Use the following function to register only the time of an event.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
sys_k_event_logger_put_timed(KERNEL_EVENT_LOGGER_CUSTOM_ID);
|
||||
|
||||
APIs
|
||||
****
|
||||
|
||||
The following APIs are provided by the :file:`k_event_logger.h` file:
|
||||
|
||||
:cpp:func:`sys_k_event_logger_register_as_collector()`
|
||||
Register the current fiber as the collector fiber.
|
||||
|
||||
:cpp:func:`sys_k_event_logger_put()`
|
||||
Enqueue a kernel event logger message with custom data.
|
||||
|
||||
:cpp:func:`sys_k_event_logger_put_timed()`
|
||||
Enqueue a kernel event logger message with the current time.
|
||||
|
||||
:cpp:func:`sys_k_event_logger_get()`
|
||||
De-queue a kernel event logger message.
|
||||
|
||||
:cpp:func:`sys_k_event_logger_get_wait()`
|
||||
De-queue a kernel event logger message. Wait if the buffer is empty.
|
||||
|
||||
:cpp:func:`sys_k_event_logger_get_wait_timeout()`
|
||||
De-queue a kernel event logger message. Wait if the buffer is empty until the timeout expires.
|
Loading…
Add table
Add a link
Reference in a new issue