/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 2018, 2019 embedded brains GmbH & Co. KG * * 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. * * 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 OWNER 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include RTEMS_STATIC_ASSERT( RTEMS_RECORD_USER_0 == 512, RTEMS_RECORD_USER_0 ); RTEMS_STATIC_ASSERT( RTEMS_RECORD_LAST == 1023, RTEMS_RECORD_LAST ); RTEMS_STATIC_ASSERT( RTEMS_RECORD_LAST + 1 == ( 1 << RTEMS_RECORD_EVENT_BITS ), RTEMS_RECORD_EVENT_BITS ); void rtems_record_produce( rtems_record_event event, rtems_record_data data ) { rtems_record_context context; rtems_record_prepare( &context ); rtems_record_add( &context, event, data ); rtems_record_commit( &context ); } void rtems_record_produce_2( rtems_record_event event_0, rtems_record_data data_0, rtems_record_event event_1, rtems_record_data data_1 ) { rtems_record_context context; rtems_record_prepare( &context ); rtems_record_add( &context, event_0, data_0 ); rtems_record_add( &context, event_1, data_1 ); rtems_record_commit( &context ); } void rtems_record_produce_n( const rtems_record_item *items, size_t n ) { rtems_record_context context; _Assert( n > 0 ); rtems_record_prepare( &context ); do { rtems_record_add( &context, items->event, items->data ); ++items; --n; } while ( n > 0 ); rtems_record_commit( &context ); } size_t _Record_String_to_items( rtems_record_event event, const char *str, size_t len, rtems_record_item *items, size_t item_count ) { size_t s; size_t i; s = 0; i = 0; while ( s < len && i < item_count ) { rtems_record_data data; size_t k; data = 0; for ( k = 0; s < len && k < sizeof( data ); ++k ) { rtems_record_data c; c = (unsigned char) str[ s ]; data |= c << ( k * 8 ); ++s; } items[ i ].event = event; items[ i ].data = data; ++i; } return i; } void _Record_Drain( Record_Control *control, uint32_t cpu_index, rtems_record_drain_visitor visitor, void *arg ) { unsigned int tail; unsigned int head; tail = _Record_Tail( control ); head = _Atomic_Load_uint( &control->head, ATOMIC_ORDER_ACQUIRE ); if ( tail == head ) { return; } control->tail = head; control->Header[ 0 ].event = RTEMS_RECORD_PROCESSOR; control->Header[ 0 ].data = cpu_index; control->Header[ 1 ].event = RTEMS_RECORD_PER_CPU_TAIL; control->Header[ 1 ].data = tail; control->Header[ 2 ].event = RTEMS_RECORD_PER_CPU_HEAD; control->Header[ 2 ].data = head; ( *visitor )( control->Header, RTEMS_ARRAY_SIZE( control->Header ), arg ); if ( _Record_Is_overflow( control, tail, head ) ) { tail = head + 1; } tail = _Record_Index( control, tail ); head = _Record_Index( control, head ); if ( tail < head ) { ( *visitor )( &control->Items[ tail ], head - tail, arg ); } else { ( *visitor )( &control->Items[ tail ], control->mask + 1 - tail, arg ); if ( head > 0 ) { ( *visitor )( &control->Items[ 0 ], head, arg ); } } } void rtems_record_drain( rtems_record_drain_visitor visitor, void *arg ) { uint32_t cpu_max; uint32_t cpu_index; cpu_max = rtems_configuration_get_maximum_processors(); for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) { Per_CPU_Control *cpu; cpu = _Per_CPU_Get_by_index( cpu_index ); _Record_Drain( cpu->record, cpu_index, visitor, arg ); } }