zephyr/kernel/nanokernel/event_logger.c

152 lines
4.3 KiB
C

/*
* Copyright (c) 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief Event logger support.
*/
#include <misc/event_logger.h>
#include <misc/ring_buffer.h>
void sys_event_logger_init(struct event_logger *logger,
uint32_t *logger_buffer, uint32_t buffer_size)
{
sys_ring_buf_init(&logger->ring_buf, buffer_size, logger_buffer);
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 *))
{
int ret;
unsigned int key;
key = irq_lock();
ret = sys_ring_buf_put(&logger->ring_buf, event_id,
logger->ring_buf.dropped_put_count, event_data,
data_size);
if (ret == 0) {
logger->ring_buf.dropped_put_count = 0;
/* inform that there is event data available on the buffer */
sem_give_fn(&(logger->sync_sema));
}
irq_unlock(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. 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 int event_logger_get(struct event_logger *logger,
uint16_t *event_id, uint8_t *dropped_event_count,
uint32_t *buffer, uint8_t *buffer_size)
{
int ret;
ret = sys_ring_buf_get(&logger->ring_buf, event_id, dropped_event_count,
buffer, buffer_size);
if (likely(!ret)) {
return *buffer_size;
}
switch (ret) {
case -EMSGSIZE:
/* 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;
case -EAGAIN:
return 0;
default:
return ret;
}
}
int sys_event_logger_get(struct event_logger *logger, uint16_t *event_id,
uint8_t *dropped_event_count, uint32_t *buffer,
uint8_t *buffer_size)
{
if (nano_fiber_sem_take(&(logger->sync_sema), TICKS_NONE)) {
return event_logger_get(logger, event_id, dropped_event_count,
buffer, buffer_size);
}
return 0;
}
int sys_event_logger_get_wait(struct event_logger *logger, uint16_t *event_id,
uint8_t *dropped_event_count, uint32_t *buffer,
uint8_t *buffer_size)
{
nano_fiber_sem_take(&(logger->sync_sema), TICKS_UNLIMITED);
return event_logger_get(logger, event_id, dropped_event_count, buffer,
buffer_size);
}
#ifdef CONFIG_NANO_TIMEOUTS
int sys_event_logger_get_wait_timeout(struct event_logger *logger,
uint16_t *event_id,
uint8_t *dropped_event_count,
uint32_t *buffer, uint8_t *buffer_size,
uint32_t timeout)
{
if (nano_fiber_sem_take(&(logger->sync_sema), timeout)) {
return event_logger_get(logger, event_id, dropped_event_count,
buffer, buffer_size);
}
return 0;
}
#endif /* CONFIG_NANO_TIMEOUTS */