Add event logger.

Add a log event tool with a single interface for the user to
add/collect the event log data.

Change-Id: Ia4b78836748c5d7e44ba1bdd50c28434e8a55d65
Signed-off-by: Yonattan Louise <yonattan.a.louise.mendoza@intel.com>
This commit is contained in:
Yonattan Louise 2015-08-11 13:32:16 -05:00 committed by Anas Nashif
commit 8c85c15a2f
7 changed files with 366 additions and 0 deletions

View file

@ -13,6 +13,7 @@ CONFIG_SYS_CLOCK_EXISTS=y
# CONFIG_INIT_STACKS is not set # CONFIG_INIT_STACKS is not set
CONFIG_XIP=y CONFIG_XIP=y
# CONFIG_ENHANCED_SECURITY is not set # CONFIG_ENHANCED_SECURITY is not set
# CONFIG_EVENT_LOGGER is not set
# #
# Nanokernel Options # Nanokernel Options

View file

@ -14,6 +14,7 @@ CONFIG_SYS_CLOCK_EXISTS=y
# CONFIG_INIT_STACKS is not set # CONFIG_INIT_STACKS is not set
CONFIG_XIP=y CONFIG_XIP=y
# CONFIG_ENHANCED_SECURITY is not set # CONFIG_ENHANCED_SECURITY is not set
# CONFIG_EVENT_LOGGER is not set
# #
# Nanokernel Options # Nanokernel Options

View file

@ -16,6 +16,7 @@ CONFIG_SYS_CLOCK_EXISTS=y
# CONFIG_INIT_STACKS is not set # CONFIG_INIT_STACKS is not set
# CONFIG_XIP is not set # CONFIG_XIP is not set
CONFIG_ENHANCED_SECURITY=y CONFIG_ENHANCED_SECURITY=y
# CONFIG_EVENT_LOGGER is not set
# #
# Security Options # Security Options

168
include/misc/event_logger.h Normal file
View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* @file
* @brief Event logger support.
*/
#include <nanokernel.h>
#include <errno.h>
#ifndef __EVENT_LOGGER_H__
#define __EVENT_LOGGER_H__
#define EVENT_HEADER_SIZE 1
struct event_header_bits {
/* length in 32-bit words */
uint32_t data_length :4;
uint32_t dropped_count :4;
uint32_t event_id :16;
uint32_t reserved :8;
};
union event_header {
uint32_t block;
struct event_header_bits bits;
};
struct event_logger {
uint32_t head;
uint32_t tail;
uint16_t dropped_event_count;
struct nano_sem sync_sema;
uint32_t *buffer;
uint32_t buffer_size;
};
/**
* @brief Initialize the event logger.
*
* @details Initialize the ring buffer.
*
* @param logger Logger to be initialized.
* @param logger_buffer Pointer to the buffer to be used by the logger.
* @param buffer_size Size of the buffer in 32-bit words.
*
* @return No return value.
*/
void sys_event_logger_init(struct event_logger *logger,
uint32_t *logger_buffer, uint32_t buffer_size);
/**
* @brief Send an event message to the logger.
*
* @details Add an event message to the ring buffer and signal the sync
* semaphore to inform that there are event messages available.
*
* @param logger Pointer to the event logger used.
* @param event_id The identification of the profiler event.
* @param data Pointer to the data of the message.
* @param data_size Size of the buffer in 32-bit words.
*
* @return No return value.
*/
void sys_event_logger_put(struct event_logger *logger, uint16_t event_id,
uint32_t *event_data, uint8_t data_size);
/**
* @brief Retrieve an event message from the logger.
*
* @details Retrieve an event message from the ring buffer and copy it to the
* provided buffer. If the provided buffer is smaller than the message
* size the function returns -EMSGSIZE. Otherwise return the number of 32-bit
* words copied. The functon retrieves messages in FIFO order. If there is no
* message in the buffer the fuction returns immediately. It can only be called
* from a fiber context.
*
* @param logger Pointer to the event logger used.
* @param buffer Pointer to the buffer where the message will be copied.
* @param buffer_size Size of the buffer in 32-bit words.
*
* @return -EMSGSIZE if the buffer size is smaller than the message size, or
* the amount of 32-bit words copied. 0 (zero) if there was no message already
* available.
*/
int sys_event_logger_get(struct event_logger *logger, uint32_t *buffer,
uint8_t buffer_size);
/**
* @brief Retrieve an event message from the logger, wait if empty.
*
* @details Retrieve an event message from the ring buffer and copy it to the
* provided buffer. If the provided buffer is smaller than the message
* size the function returns -EMSGSIZE. Otherwise return the number of 32-bit
* words copied. The functon retrieves messages in FIFO order. The caller pends
* if there is no message available in the buffer. It can only be called from a
* fiber context.
*
* @param logger Pointer to the event logger used.
* @param buffer Pointer to the buffer where the message will be copied.
* @param buffer_size Size of the buffer in 32-bit words.
*
* @return -EMSGSIZE if the buffer size is smaller than the message size. Or
* the amount of DWORDs copied.
*/
int sys_event_logger_get_wait(struct event_logger *logger, uint32_t *buffer,
uint8_t buffer_size);
#ifdef CONFIG_NANO_TIMEOUTS
/**
* @brief Retrieve an event message from the logger, wait with a timeout if
* empty.
*
* @details Retrieve an event message from the ring buffer and copy it to the
* provided buffer. If the provided buffer is smaller than the message
* size the function returns -EMSGSIZE. Otherwise return the number of dwords
* copied. The functon retrieves messages in FIFO order. The caller pends if
* there is no message available in the buffer until a new message is added or
* the timeout expires. It can only be called from a fiber context.
*
* @param logger Pointer to the event logger used.
* @param buffer Pointer to the buffer where the message will be copied.
* @param buffer_size Size of the buffer.
* @param timeout Timeout in ticks.
*
* @return -EMSGSIZE if the buffer size is smaller than the message size. Or
* the amount of 32-bit words copied. 0 (zero) if the timeout expired and there
* was no message already available.
*/
int sys_event_logger_get_wait_timeout(struct event_logger *logger,
uint32_t *buffer, uint8_t buffer_size, uint32_t timeout);
#endif /* CONFIG_NANO_TIMEOUTS */
#endif /* __EVENT_LOGGER_H__ */

View file

@ -103,6 +103,14 @@ config ENHANCED_SECURITY
Users can customize these settings using the CUSTOM_SECURITY option Users can customize these settings using the CUSTOM_SECURITY option
in the "Security Options" menu. in the "Security Options" menu.
config EVENT_LOGGER
bool
prompt "Enable event logger"
default n
help
Enable event logging feature. Allow the usage of a ring buffer to
transmit event messages with a single interface to collect them.
menu "Security Options" menu "Security Options"
depends on ENHANCED_SECURITY depends on ENHANCED_SECURITY

View file

@ -13,3 +13,4 @@ obj-$(CONFIG_STACK_CANARIES) += compiler_stack_protect.o
obj-$(CONFIG_INT_LATENCY_BENCHMARK) += int_latency_bench.o obj-$(CONFIG_INT_LATENCY_BENCHMARK) += int_latency_bench.o
obj-$(CONFIG_ADVANCED_POWER_MANAGEMENT) += idle.o obj-$(CONFIG_ADVANCED_POWER_MANAGEMENT) += idle.o
obj-$(CONFIG_NANO_TIMERS) += nano_timer.o obj-$(CONFIG_NANO_TIMERS) += nano_timer.o
obj-$(CONFIG_EVENT_LOGGER) += event_logger.o

View file

@ -0,0 +1,186 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* @file
* @brief Event logger support.
*/
#include <misc/event_logger.h>
void sys_event_logger_init(struct event_logger *logger,
uint32_t *logger_buffer, uint32_t buffer_size)
{
logger->head = logger->tail = 0;
logger->dropped_event_count = 0;
logger->buffer = logger_buffer;
logger->buffer_size = buffer_size;
nano_sem_init(&(logger->sync_sema));
}
static void event_logger_put(struct event_logger *logger, uint16_t event_id,
uint32_t *event_data, uint8_t data_size,
void(*sem_give_fn)(struct nano_sem *))
{
unsigned int key;
unsigned int buffer_capacity_used;
union event_header header;
int i;
/* Lock interrupt to be sure this function will be atomic */
key = irq_lock_inline();
buffer_capacity_used = (logger->head - logger->tail +
logger->buffer_size) % logger->buffer_size;
/* check if there is space to the new event */
if (buffer_capacity_used + EVENT_HEADER_SIZE + data_size >=
logger->buffer_size) {
(logger->dropped_event_count)++;
} else {
/* build the header */
header.bits.data_length = data_size;
header.bits.event_id = event_id;
header.bits.dropped_count = logger->dropped_event_count;
logger->dropped_event_count = 0;
/* copy the header to the buffer */
logger->buffer[logger->head] = header.block;
logger->head = (logger->head + EVENT_HEADER_SIZE) %
logger->buffer_size;
/* copy the extra data to the buffer */
for (i=0; i < header.bits.data_length; ++i) {
logger->buffer[(logger->head + i) %
logger->buffer_size] = event_data[i];
}
logger->head = (logger->head + header.bits.data_length) %
logger->buffer_size;
/* inform that there is event data available on the buffer */
sem_give_fn(&(logger->sync_sema));
}
irq_unlock_inline(key);
}
void sys_event_logger_put(struct event_logger *logger, uint16_t event_id,
uint32_t *event_data, uint8_t data_size)
{
event_logger_put(logger, event_id, event_data, data_size, nano_sem_give);
}
/**
* @brief Send an event message to the logger with a non preemptible
* behaviour.
*
* @details Add an event message to the ring buffer and signal the sync
* semaphore using the internal function _sem_give_non_preemptible to inform
* that there are event messages available, avoiding the preemptible
* behaviour when the function is called from a task context. This function
* should be only used for special cases where the sys_event_logger_put
* does not satisfy the needs.
*
* @param logger Pointer to the event logger used.
* @param event_id The identification of the profiler event.
* @param data Pointer to the data of the message.
* @param data_size Size of the buffer in 32-bit words.
*
* @return No return value.
*/
void _sys_event_logger_put_non_preemptible(struct event_logger *logger,
uint16_t event_id, uint32_t *event_data, uint8_t data_size)
{
extern void _sem_give_non_preemptible(struct nano_sem *sem);
event_logger_put(logger, event_id, event_data, data_size,
_sem_give_non_preemptible);
}
static inline int event_logger_get(struct event_logger *logger,
uint32_t *buffer, uint8_t buffer_size)
{
int i;
union event_header *header;
/* obtain the header */
header = (union event_header *) &(logger->buffer[logger->tail]);
if (buffer_size < EVENT_HEADER_SIZE + header->bits.data_length) {
/* if the user can not retrieve the message, we increase the semaphore
* to indicate that the message remains in the buffer */
nano_fiber_sem_give(&(logger->sync_sema));
return -EMSGSIZE;
}
for (i=0; i < header->bits.data_length + EVENT_HEADER_SIZE; i++) {
buffer[i] = logger->buffer[(logger->tail + i) %
logger->buffer_size];
}
logger->tail = (logger->tail + header->bits.data_length +
EVENT_HEADER_SIZE) % logger->buffer_size;
return header->bits.data_length + EVENT_HEADER_SIZE;
}
int sys_event_logger_get(struct event_logger *logger, uint32_t *buffer,
uint8_t buffer_size)
{
if (nano_fiber_sem_take(&(logger->sync_sema))) {
return sys_event_logger_get(logger, buffer, buffer_size);
}
return 0;
}
int sys_event_logger_get_wait(struct event_logger *logger, uint32_t *buffer,
uint8_t buffer_size)
{
nano_fiber_sem_take_wait(&(logger->sync_sema));
return event_logger_get(logger, buffer, buffer_size);
}
#ifdef CONFIG_NANO_TIMEOUTS
int sys_event_logger_get_wait_timeout(struct event_logger *logger,
uint32_t *buffer, uint8_t buffer_size, uint32_t timeout)
{
if (nano_fiber_sem_take_wait_timeout(&(logger->sync_sema), timeout)) {
return event_logger_get(logger, buffer, buffer_size);
}
return 0;
}
#endif /* CONFIG_NANO_TIMEOUTS */