From 920f8d88978cf91aa38750107dc8a86f388be632 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 11 Oct 2024 02:36:27 +0200 Subject: [PATCH] record: Rework client The ring buffer overflow handling is already performed by rtems_record_fetch(). --- cpukit/include/rtems/recordclient.h | 56 ++- cpukit/libtrace/record/record-client.c | 484 ++++++++++++------------- testsuites/libtests/record02/init.c | 46 ++- 3 files changed, 290 insertions(+), 296 deletions(-) diff --git a/cpukit/include/rtems/recordclient.h b/cpukit/include/rtems/recordclient.h index 021e485b84..dab0f703ce 100644 --- a/cpukit/include/rtems/recordclient.h +++ b/cpukit/include/rtems/recordclient.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (C) 2018, 2019 embedded brains GmbH & Co. KG + * Copyright (C) 2018, 2024 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -72,43 +72,28 @@ typedef rtems_record_client_status ( *rtems_record_client_handler )( void *arg ); +typedef struct { + uint64_t uptime_bt; + uint32_t time_last; + uint64_t time_accumulated; +} rtems_record_client_uptime; + +/** + * @brief This constant defines the maximum capacity of the hold back item + * storage in case a reallocation is necessary. + */ +#define RTEMS_RECORD_CLIENT_HOLD_BACK_REALLOCATION_LIMIT 0x100000 + typedef struct { /** * @brief Event time to uptime maintenance. */ - struct { - uint64_t bt; - uint32_t time_at_bt; - uint32_t time_last; - uint32_t time_accumulated; - } uptime; + rtems_record_client_uptime uptime; /** - * @brief The current or previous ring buffer tail. - * - * Indexed by the tail_head_index member. + * @brief Last RTEMS_RECORD_UPTIME_LOW data. */ - uint32_t tail[ 2 ]; - - /** - * @brief The current or previous ring buffer head. - * - * Indexed by the tail_head_index member. - */ - uint32_t head[ 2 ]; - - /** - * @brief The index of the tail and head members. - * - * This index is used to maintain the current and previous tail/head - * positions to detect ring buffer overflows. - */ - size_t tail_head_index; - - /** - * @brief Count of lost items due to ring buffer overflows. - */ - uint32_t overflow; + uint32_t uptime_low; /** * @brief If true, then hold back items. @@ -123,6 +108,11 @@ typedef struct { */ rtems_record_item_64 *items; + /** + * @brief The item capacity of the hold back storage. + */ + size_t item_capacity; + /** * @brief The index for the next hold back item. */ @@ -134,7 +124,7 @@ typedef struct rtems_record_client_context { rtems_record_client_per_cpu per_cpu[ RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT ]; uint32_t cpu; uint32_t cpu_count; - uint32_t count; + uint32_t per_cpu_items; union { rtems_record_item_32 format_32; rtems_record_item_64 format_64; @@ -163,7 +153,7 @@ typedef struct rtems_record_client_context { * @param handler The handler is invoked for each received record item. * @param arg The handler argument. */ -void rtems_record_client_init( +rtems_record_client_status rtems_record_client_init( rtems_record_client_context *ctx, rtems_record_client_handler handler, void *arg diff --git a/cpukit/libtrace/record/record-client.c b/cpukit/libtrace/record/record-client.c index 257fc34fc4..f53815b1a0 100644 --- a/cpukit/libtrace/record/record-client.c +++ b/cpukit/libtrace/record/record-client.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (C) 2018, 2019 embedded brains GmbH & Co. KG + * Copyright (C) 2018, 2024 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,7 +38,6 @@ #include #include -#include #define TIME_MASK ( ( UINT32_C( 1 ) << RTEMS_RECORD_TIME_BITS ) - 1 ) @@ -71,6 +70,50 @@ static rtems_record_client_status error( return status; } +static rtems_record_client_status process_per_cpu_count( + rtems_record_client_context *ctx, + uint64_t data +) +{ + size_t item_capacity; + uint32_t cpu; + + if ( ctx->per_cpu_items != 0 ) { + return error( ctx, RTEMS_RECORD_CLIENT_ERROR_DOUBLE_PER_CPU_COUNT ); + } + + if ( ctx->cpu_count == 0 ) { + return error( ctx, RTEMS_RECORD_CLIENT_ERROR_NO_CPU_MAX ); + } + + ctx->per_cpu_items = (uint32_t) data; + + /* + * Use two times the ring buffer capacity so that it remains a power of two + * and can hold the RTEMS_RECORD_PROCESSOR and RTEMS_RECORD_PER_CPU_OVERFLOW + * items produced by rtems_record_fetch(). + */ + item_capacity = 2 * ctx->per_cpu_items; + + for ( cpu = 0; cpu < ctx->cpu_count; ++cpu ) { + rtems_record_client_per_cpu *per_cpu; + + per_cpu = &ctx->per_cpu[ cpu ]; + per_cpu->items = realloc( + per_cpu->items, + item_capacity * sizeof( *per_cpu->items ) + ); + + if ( per_cpu->items == NULL ) { + return error( ctx, RTEMS_RECORD_CLIENT_ERROR_NO_MEMORY ); + } + + per_cpu->item_capacity = item_capacity; + } + + return RTEMS_RECORD_CLIENT_SUCCESS; +} + static void set_to_bt_scaler( rtems_record_client_context *ctx, uint32_t frequency @@ -82,15 +125,62 @@ static void set_to_bt_scaler( ctx->to_bt_scaler = ( ( bin_per_s << 31 ) + frequency - 1 ) / frequency; } +static bool has_time( rtems_record_event event ) +{ + switch ( event ) { + case RTEMS_RECORD_ARCH: + case RTEMS_RECORD_BSP: + case RTEMS_RECORD_FREQUENCY: + case RTEMS_RECORD_MULTILIB: + case RTEMS_RECORD_PER_CPU_COUNT: + case RTEMS_RECORD_PER_CPU_OVERFLOW: + case RTEMS_RECORD_PROCESSOR: + case RTEMS_RECORD_PROCESSOR_MAXIMUM: + case RTEMS_RECORD_THREAD_ID: + case RTEMS_RECORD_THREAD_NAME: + case RTEMS_RECORD_TOOLS: + case RTEMS_RECORD_VERSION: + case RTEMS_RECORD_VERSION_CONTROL_KEY: + return false; + default: + return true; + } +} + +static uint64_t time_bt( + const rtems_record_client_context *ctx, + rtems_record_client_per_cpu *per_cpu, + uint32_t time, + rtems_record_event event +) +{ + uint64_t bt; + uint64_t time_accumulated; + + time_accumulated = per_cpu->uptime.time_accumulated; + + if ( has_time( event) ) { + time_accumulated += ( time - per_cpu->uptime.time_last ) & TIME_MASK; + per_cpu->uptime.time_last = time; + per_cpu->uptime.time_accumulated = time_accumulated; + } + + bt = per_cpu->uptime.uptime_bt; + bt += ( time_accumulated * ctx->to_bt_scaler ) >> 31; + + return bt; +} + static rtems_record_client_status call_handler( const rtems_record_client_context *ctx, - uint64_t bt, + rtems_record_client_per_cpu *per_cpu, + uint32_t time, rtems_record_event event, uint64_t data ) { return ( *ctx->handler )( - bt, + time_bt( ctx, per_cpu, time, event ), ctx->cpu, event, data, @@ -98,205 +188,61 @@ static rtems_record_client_status call_handler( ); } -static void signal_overflow( - rtems_record_client_per_cpu *per_cpu, - uint32_t data -) -{ - per_cpu->hold_back = true; - per_cpu->item_index = 0; - per_cpu->overflow += data; -} - -static void resolve_hold_back( +static rtems_record_client_status resolve_hold_back( rtems_record_client_context *ctx, rtems_record_client_per_cpu *per_cpu ) { - if ( per_cpu->hold_back ) { - uint32_t last_tail; - uint32_t last_head; - uint32_t last_capacity; - uint32_t new_head; - uint32_t new_content; - uint32_t begin_index; - uint32_t index; - uint32_t first; - uint32_t last; - uint32_t delta; - uint64_t uptime; + rtems_record_item_64 *items; + uint32_t last; + uint64_t accumulated; + size_t index; + rtems_record_client_uptime uptime; + + items = per_cpu->items; + last = per_cpu->uptime.time_last; + accumulated = 0; + + for ( index = per_cpu->item_index; index > 0; --index ) { + uint32_t time_event; + + time_event = items[ index - 1 ].event; + + if ( has_time( RTEMS_RECORD_GET_EVENT( time_event ) ) ) { + uint32_t time; + + time = RTEMS_RECORD_GET_TIME( time_event ); + accumulated += ( last - time ) & TIME_MASK; + last = time; + } + } + + uptime = per_cpu->uptime; + per_cpu->uptime.uptime_bt -= ( accumulated * ctx->to_bt_scaler ) >> 31; + per_cpu->uptime.time_last = last; + per_cpu->uptime.time_accumulated = 0; + + for ( index = 0; index < per_cpu->item_index; ++index ) { + uint32_t time_event; rtems_record_client_status status; - last_head = per_cpu->head[ per_cpu->tail_head_index ]; - last_tail = per_cpu->tail[ per_cpu->tail_head_index ]; - new_head = per_cpu->head[ per_cpu->tail_head_index ^ 1 ]; - last_capacity = ( last_tail - last_head - 1 ) & ( ctx->count - 1 ); - new_content = new_head - last_head; + time_event = items[ index ].event; + status = call_handler( + ctx, + per_cpu, + RTEMS_RECORD_GET_TIME( time_event ), + RTEMS_RECORD_GET_EVENT( time_event ), + items[ index ].data + ); - if ( new_content > last_capacity ) { - begin_index = new_content - last_capacity; - per_cpu->overflow += begin_index; - } else { - begin_index = 0; - } - - if ( begin_index >= per_cpu->item_index ) { - per_cpu->item_index = 0; - return; - } - - per_cpu->hold_back = false; - - first = RTEMS_RECORD_GET_TIME( per_cpu->items[ begin_index ].event ); - last = first; - delta = 0; - uptime = 0; - - for ( index = begin_index; index < per_cpu->item_index; ++index ) { - const rtems_record_item_64 *item; - rtems_record_event event; - uint32_t time; - - item = &per_cpu->items[ index ]; - event = RTEMS_RECORD_GET_EVENT( item->event ); - time = RTEMS_RECORD_GET_TIME( item->event ); - delta += ( time - last ) & TIME_MASK; - last = time; - - if ( - event == RTEMS_RECORD_UPTIME_LOW - && index + 1 < per_cpu->item_index - && RTEMS_RECORD_GET_EVENT( ( item + 1 )->event ) - == RTEMS_RECORD_UPTIME_HIGH - ) { - uptime = (uint32_t) item->data; - uptime += ( item + 1 )->data << 32; - break; - } - } - - per_cpu->uptime.bt = uptime - ( ( delta * ctx->to_bt_scaler ) >> 31 ); - per_cpu->uptime.time_at_bt = first; - per_cpu->uptime.time_last = first; - per_cpu->uptime.time_accumulated = 0; - - if ( per_cpu->overflow > 0 ) { - call_handler( - ctx, - per_cpu->uptime.bt, - RTEMS_RECORD_PER_CPU_OVERFLOW, - per_cpu->overflow - ); - per_cpu->overflow = 0; - } - - for ( index = begin_index; index < per_cpu->item_index; ++index ) { - const rtems_record_item_64 *item; - - item = &per_cpu->items[ index ]; - status = visit( ctx, item->event, item->data ); - _Assert_Unused_variable_equals(status, RTEMS_RECORD_CLIENT_SUCCESS); + if ( status != RTEMS_RECORD_CLIENT_SUCCESS ) { + return status; } } -} -static void process_per_cpu_head( - rtems_record_client_context *ctx, - rtems_record_client_per_cpu *per_cpu, - uint64_t data -) -{ - uint32_t last_tail; - uint32_t last_head; - uint32_t last_capacity; - uint32_t new_tail; - uint32_t new_head; - uint32_t new_content; - uint32_t content; - - new_tail = per_cpu->tail[ per_cpu->tail_head_index ]; - new_head = (uint32_t) data; - content = new_head - new_tail; - - per_cpu->head[ per_cpu->tail_head_index ] = new_head; - per_cpu->tail_head_index ^= 1; - - if ( content >= ctx->count ) { - /* - * This is a complete ring buffer overflow, the server will detect this - * also. It sets the tail to the head plus one and sends us all the - * content. This reduces the ring buffer capacity to zero. So, during - * transfer, new events will overwrite items in transfer. This is handled - * by resolve_hold_back(). - */ - per_cpu->tail[ per_cpu->tail_head_index ^ 1 ] = new_head + 1; - signal_overflow( per_cpu, content - ctx->count + 1 ); - return; - } - - last_tail = per_cpu->tail[ per_cpu->tail_head_index ]; - last_head = per_cpu->head[ per_cpu->tail_head_index ]; - - if ( last_tail == last_head ) { - if ( per_cpu->uptime.bt == 0 ) { - /* - * This is a special case during initial ramp up. We hold back the items - * to deduce the uptime of the first item via resolve_hold_back(). - */ - per_cpu->hold_back = true; - } else { - resolve_hold_back( ctx, per_cpu ); - } - - return; - } - - last_capacity = ( last_tail - last_head - 1 ) & ( ctx->count - 1 ); - new_content = new_head - last_head; - - if ( new_content <= last_capacity || per_cpu->hold_back ) { - resolve_hold_back( ctx, per_cpu ); - return; - } - - signal_overflow( per_cpu, new_content - last_capacity ); -} - -static rtems_record_client_status process_per_cpu_count( - rtems_record_client_context *ctx, - uint64_t data -) -{ - size_t per_cpu_items; - rtems_record_item_64 *items; - uint32_t cpu; - - if ( ctx->count != 0 ) { - return error( ctx, RTEMS_RECORD_CLIENT_ERROR_DOUBLE_PER_CPU_COUNT ); - } - - if ( ctx->cpu_count == 0 ) { - return error( ctx, RTEMS_RECORD_CLIENT_ERROR_NO_CPU_MAX ); - } - - ctx->count = (uint32_t) data; - - /* - * The ring buffer capacity plus two items for RTEMS_RECORD_PROCESSOR and - * RTEMS_RECORD_PER_CPU_TAIL. - */ - per_cpu_items = ctx->count + 1; - - items = malloc( per_cpu_items * ctx->cpu_count * sizeof( *items ) ); - - if ( items == NULL ) { - return error( ctx, RTEMS_RECORD_CLIENT_ERROR_NO_MEMORY ); - } - - for ( cpu = 0; cpu < ctx->cpu_count; ++cpu ) { - ctx->per_cpu[ cpu ].items = items; - items += per_cpu_items; - } + per_cpu->uptime = uptime; + per_cpu->hold_back = false; + per_cpu->item_index = 0; return RTEMS_RECORD_CLIENT_SUCCESS; } @@ -305,52 +251,36 @@ static rtems_record_client_status hold_back( rtems_record_client_context *ctx, rtems_record_client_per_cpu *per_cpu, uint32_t time_event, - rtems_record_event event, uint64_t data ) { - if ( event != RTEMS_RECORD_PER_CPU_HEAD ) { - uint32_t item_index; + uint32_t item_index; - item_index = per_cpu->item_index; + item_index = per_cpu->item_index; - if ( item_index <= ctx->count ) { - per_cpu->items[ item_index ].event = time_event; - per_cpu->items[ item_index ].data = data; - per_cpu->item_index = item_index + 1; - } else { + if ( item_index >= per_cpu->item_capacity ) { + if ( item_index >= RTEMS_RECORD_CLIENT_HOLD_BACK_REALLOCATION_LIMIT ) { return error( ctx, RTEMS_RECORD_CLIENT_ERROR_PER_CPU_ITEMS_OVERFLOW ); } - } else { - return call_handler( ctx, 0, RTEMS_RECORD_GET_EVENT( time_event ), data ); + + per_cpu->item_capacity = 2 * item_index; + per_cpu->items = realloc( + per_cpu->items, + per_cpu->item_capacity * sizeof( *per_cpu->items ) + ); + + if ( per_cpu->items == NULL ) { + return error( ctx, RTEMS_RECORD_CLIENT_ERROR_NO_MEMORY ); + } } + per_cpu->items[ item_index ].event = time_event; + per_cpu->items[ item_index ].data = data; + per_cpu->item_index = item_index + 1; + return RTEMS_RECORD_CLIENT_SUCCESS; } -static uint64_t time_bt( - const rtems_record_client_context *ctx, - rtems_record_client_per_cpu *per_cpu, - uint32_t time -) -{ - uint64_t bt; - - if ( time != 0 ) { - uint32_t delta; - - delta = ( time - per_cpu->uptime.time_last ) & TIME_MASK; - per_cpu->uptime.time_last = time; - per_cpu->uptime.time_accumulated += delta; - bt = ( per_cpu->uptime.time_accumulated * ctx->to_bt_scaler ) >> 31; - bt += per_cpu->uptime.bt; - } else { - bt = 0; - } - - return bt; -} - static rtems_record_client_status visit( rtems_record_client_context *ctx, uint32_t time_event, @@ -361,10 +291,12 @@ static rtems_record_client_status visit( uint32_t time; rtems_record_event event; rtems_record_client_status status; + bool do_hold_back; per_cpu = &ctx->per_cpu[ ctx->cpu ]; time = RTEMS_RECORD_GET_TIME( time_event ); event = RTEMS_RECORD_GET_EVENT( time_event ); + do_hold_back = per_cpu->hold_back; switch ( event ) { case RTEMS_RECORD_PROCESSOR: @@ -376,21 +308,21 @@ static rtems_record_client_status visit( per_cpu = &ctx->per_cpu[ ctx->cpu ]; break; case RTEMS_RECORD_UPTIME_LOW: - per_cpu->uptime.bt = (uint32_t) data; - per_cpu->uptime.time_at_bt = time; - per_cpu->uptime.time_last = time; - per_cpu->uptime.time_accumulated = 0; - time = 0; + per_cpu->uptime_low = (uint32_t) data; break; case RTEMS_RECORD_UPTIME_HIGH: - per_cpu->uptime.bt += data << 32; - time = 0; - break; - case RTEMS_RECORD_PER_CPU_TAIL: - per_cpu->tail[ per_cpu->tail_head_index ] = (uint32_t) data; - break; - case RTEMS_RECORD_PER_CPU_HEAD: - process_per_cpu_head( ctx, per_cpu, data ); + per_cpu->uptime.uptime_bt = ( data << 32 ) | per_cpu->uptime_low; + per_cpu->uptime.time_last = time; + per_cpu->uptime.time_accumulated = 0; + + if (do_hold_back) { + status = resolve_hold_back( ctx, per_cpu ); + + if ( status != RTEMS_RECORD_CLIENT_SUCCESS ) { + return status; + } + } + break; case RTEMS_RECORD_PROCESSOR_MAXIMUM: if ( data >= RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT ) { @@ -402,6 +334,7 @@ static rtems_record_client_status visit( } ctx->cpu_count = (uint32_t) data + 1; + do_hold_back = false; break; case RTEMS_RECORD_PER_CPU_COUNT: status = process_per_cpu_count( ctx, data ); @@ -410,6 +343,10 @@ static rtems_record_client_status visit( return status; } + break; + case RTEMS_RECORD_PER_CPU_OVERFLOW: + do_hold_back = true; + per_cpu->hold_back = true; break; case RTEMS_RECORD_FREQUENCY: set_to_bt_scaler( ctx, (uint32_t) data ); @@ -419,16 +356,17 @@ static rtems_record_client_status visit( return error( ctx, RTEMS_RECORD_CLIENT_ERROR_UNSUPPORTED_VERSION ); } + do_hold_back = false; break; default: break; } - if ( per_cpu->hold_back ) { - return hold_back( ctx, per_cpu, time_event, event, data ); + if ( do_hold_back ) { + return hold_back( ctx, per_cpu, time_event, data ); } - return call_handler( ctx, time_bt( ctx, per_cpu, time ), event, data ); + return call_handler( ctx, per_cpu, time, event, data ); } static rtems_record_client_status consume_32( @@ -688,12 +626,14 @@ static rtems_record_client_status consume_init( return RTEMS_RECORD_CLIENT_SUCCESS; } -void rtems_record_client_init( +rtems_record_client_status rtems_record_client_init( rtems_record_client_context *ctx, rtems_record_client_handler handler, void *arg ) { + uint32_t cpu; + ctx = memset( ctx, 0, sizeof( *ctx ) ); ctx->to_bt_scaler = UINT64_C( 1 ) << 31; ctx->handler = handler; @@ -701,6 +641,12 @@ void rtems_record_client_init( ctx->todo = sizeof( ctx->header ); ctx->pos = &ctx->header; ctx->consume = consume_init; + + for ( cpu = 0; cpu < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++cpu ) { + ctx->per_cpu[ cpu ].hold_back = true; + } + + return RTEMS_RECORD_CLIENT_SUCCESS; } rtems_record_client_status rtems_record_client_run( @@ -712,6 +658,44 @@ rtems_record_client_status rtems_record_client_run( return ( *ctx->consume )( ctx, buf, n ); } +static void calculate_best_effort_uptime( + rtems_record_client_context *ctx, + rtems_record_client_per_cpu *per_cpu +) +{ + rtems_record_item_64 *items; + uint32_t last; + uint64_t accumulated; + size_t index; + + items = per_cpu->items; + accumulated = 0; + + if ( per_cpu->uptime.uptime_bt != 0 ) { + last = per_cpu->uptime.time_last; + } else { + last = RTEMS_RECORD_GET_TIME( items[ 0 ].event ); + } + + for ( index = 0; index < per_cpu->item_index; ++index ) { + uint32_t time_event; + + time_event = items[ index ].event; + + if ( has_time( RTEMS_RECORD_GET_EVENT( time_event ) ) ) { + uint32_t time; + + time = RTEMS_RECORD_GET_TIME( time_event ); + accumulated += ( time - last ) & TIME_MASK; + last = time; + } + } + + per_cpu->uptime.uptime_bt += ( accumulated * ctx->to_bt_scaler ) >> 31; + per_cpu->uptime.time_last = last; + per_cpu->uptime.time_accumulated = 0; +} + void rtems_record_client_destroy( rtems_record_client_context *ctx ) @@ -723,10 +707,12 @@ void rtems_record_client_destroy( ctx->cpu = cpu; per_cpu = &ctx->per_cpu[ cpu ]; - per_cpu->head[ per_cpu->tail_head_index ^ 1 ] = - per_cpu->head[ per_cpu->tail_head_index ]; - resolve_hold_back( ctx, per_cpu ); - } - free( ctx->per_cpu[ 0 ].items ); + if ( per_cpu->hold_back && per_cpu->item_index > 0 ) { + calculate_best_effort_uptime( ctx, per_cpu ); + (void) resolve_hold_back( ctx, per_cpu ); + } + + free( per_cpu->items ); + } } diff --git a/testsuites/libtests/record02/init.c b/testsuites/libtests/record02/init.c index 783a335c4e..337b88d0d4 100644 --- a/testsuites/libtests/record02/init.c +++ b/testsuites/libtests/record02/init.c @@ -53,25 +53,25 @@ static rtems_record_client_status client_handler( void *arg ) { + uint32_t seconds; + uint32_t nanoseconds; + (void) arg; - if ( bt != 0 ) { - uint32_t seconds; - uint32_t nanoseconds; - - rtems_record_client_bintime_to_seconds_and_nanoseconds( - bt, - &seconds, - &nanoseconds - ); - - printf( "%" PRIu32 ".%09" PRIu32 ":", seconds, nanoseconds ); - } else { - printf( "*:" ); + if (event == RTEMS_RECORD_USER_5) { + return RTEMS_RECORD_CLIENT_SUCCESS; } + rtems_record_client_bintime_to_seconds_and_nanoseconds( + bt, + &seconds, + &nanoseconds + ); printf( + "%" PRIu32 ".%09" PRIu32 ":" "%" PRIu32 ":%s:%" PRIx64 "\n", + seconds, + nanoseconds, cpu, rtems_record_event_text( event ), data @@ -163,7 +163,17 @@ static void fetch(test_context *ctx) ); rtems_test_assert(cs == RTEMS_RECORD_CLIENT_SUCCESS); } while (fs == RTEMS_RECORD_FETCH_CONTINUE); +} +static void overflow(void) +{ + int i; + + for (i = 0; i < 512; ++i) { + rtems_record_produce(RTEMS_RECORD_USER_5, 0); + } + + rtems_record_produce(RTEMS_RECORD_USER_6, 0); } static void Init(rtems_task_argument arg) @@ -172,17 +182,25 @@ static void Init(rtems_task_argument arg) Record_Stream_header header; size_t size; rtems_record_client_status cs; + rtems_interrupt_level level; TEST_BEGIN(); ctx = &test_instance; generate_events(); - rtems_record_client_init(&ctx->client, client_handler, NULL); + cs = rtems_record_client_init(&ctx->client, client_handler, NULL); + rtems_test_assert(cs == RTEMS_RECORD_CLIENT_SUCCESS); size = _Record_Stream_header_initialize(&header); cs = rtems_record_client_run(&ctx->client, &header, size); rtems_test_assert(cs == RTEMS_RECORD_CLIENT_SUCCESS); fetch(ctx); + + rtems_interrupt_local_disable(level); + overflow(); + fetch(ctx); + rtems_interrupt_local_enable(level); + rtems_record_client_destroy(&ctx->client); generate_events();