/* * 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 #include 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))) { 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_wait(&(logger->sync_sema)); 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_wait_timeout(&(logger->sync_sema), timeout)) { return event_logger_get(logger, event_id, dropped_event_count, buffer, buffer_size); } return 0; } #endif /* CONFIG_NANO_TIMEOUTS */