From 036717eda4de437336a86ca67253b7e32f67463c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 26 Jul 2019 16:36:10 +0200 Subject: record: Add support for thread names --- cpukit/include/rtems/recorddata.h | 4 +- cpukit/libtrace/record/record-server.c | 70 +++++++++++++++++++++++++++++++++ cpukit/libtrace/record/record-text.c | 2 +- cpukit/libtrace/record/record-userext.c | 36 ++++++++++++++--- testsuites/libtests/record01/init.c | 32 +++++++++++++++ 5 files changed, 136 insertions(+), 8 deletions(-) diff --git a/cpukit/include/rtems/recorddata.h b/cpukit/include/rtems/recorddata.h index 61a6311735..607955c596 100644 --- a/cpukit/include/rtems/recorddata.h +++ b/cpukit/include/rtems/recorddata.h @@ -55,7 +55,7 @@ extern "C" { * The record version reflects the record event definitions. It is reported by * the RTEMS_RECORD_VERSION event. */ -#define RTEMS_RECORD_THE_VERSION 4 +#define RTEMS_RECORD_THE_VERSION 5 /** * @brief The items are in 32-bit little-endian format. @@ -291,6 +291,7 @@ typedef enum { RTEMS_RECORD_THREAD_EXIT, RTEMS_RECORD_THREAD_EXITTED, RTEMS_RECORD_THREAD_ID, + RTEMS_RECORD_THREAD_NAME, RTEMS_RECORD_THREAD_PRIO_CURRENT_HIGH, RTEMS_RECORD_THREAD_PRIO_CURRENT_LOW, RTEMS_RECORD_THREAD_PRIO_REAL_HIGH, @@ -607,7 +608,6 @@ typedef enum { RTEMS_RECORD_SYSTEM_508, RTEMS_RECORD_SYSTEM_509, RTEMS_RECORD_SYSTEM_510, - RTEMS_RECORD_SYSTEM_511, /* There are 512 events reserved for the user */ RTEMS_RECORD_USER_0, diff --git a/cpukit/libtrace/record/record-server.c b/cpukit/libtrace/record/record-server.c index 840924a24a..b8519cc6cb 100644 --- a/cpukit/libtrace/record/record-server.c +++ b/cpukit/libtrace/record/record-server.c @@ -30,6 +30,7 @@ #endif #include +#include #include #include @@ -165,6 +166,74 @@ static void send_header( int fd ) (void) write( fd, &header, sizeof( header ) ); } +typedef struct { + int fd; + size_t index; + rtems_record_item items[ 128 ]; +} thread_names_context; + +static void thread_names_produce( + thread_names_context *ctx, + rtems_record_event event, + rtems_record_data data +) +{ + size_t i; + + i = ctx->index; + ctx->items[ i ].event = RTEMS_RECORD_TIME_EVENT( 0, event ); + ctx->items[ i ].data = data; + + if (i == RTEMS_ARRAY_SIZE(ctx->items) - 2) { + ctx->index = 0; + (void) write( ctx->fd, ctx->items, sizeof( ctx->items ) ); + } else { + ctx->index = i + 1; + } +} + +static bool thread_names_visitor( rtems_tcb *tcb, void *arg ) +{ + thread_names_context *ctx; + char name[ 2 * THREAD_DEFAULT_MAXIMUM_NAME_SIZE ]; + size_t n; + size_t i; + rtems_record_data data; + + ctx = arg; + thread_names_produce( ctx, RTEMS_RECORD_THREAD_ID, tcb->Object.id ); + n = _Thread_Get_name( tcb, name, sizeof( name ) ); + i = 0; + + while ( i < n ) { + size_t j; + + data = 0; + + for ( j = 0; i < n && j < sizeof( data ); ++j ) { + data = ( data << 8 ) | name[ i ]; + ++i; + } + + thread_names_produce( ctx, RTEMS_RECORD_THREAD_NAME, data ); + } + + return false; +} + +static void send_thread_names( int fd ) +{ + thread_names_context ctx; + + ctx.fd = fd; + ctx.index = 0; + rtems_task_iterate( thread_names_visitor, &ctx ); + + if ( ctx.index > 0 ) { + (void) write( ctx.fd, ctx.items, ctx.index * sizeof( ctx.items[ 0 ] ) ); + } +} + void rtems_record_server( uint16_t port, rtems_interval period ) { rtems_status_code sc; @@ -216,6 +285,7 @@ void rtems_record_server( uint16_t port, rtems_interval period ) wait( RTEMS_NO_WAIT ); (void) rtems_timer_fire_after( timer, period, wakeup_timer, &self ); send_header( cd ); + send_thread_names( cd ); while ( true ) { n = rtems_record_writev( cd, &written ); diff --git a/cpukit/libtrace/record/record-text.c b/cpukit/libtrace/record/record-text.c index cbc623aa1f..5652ab051c 100644 --- a/cpukit/libtrace/record/record-text.c +++ b/cpukit/libtrace/record/record-text.c @@ -236,6 +236,7 @@ static const char * const event_text[] = { [ RTEMS_RECORD_THREAD_EXIT ] = "THREAD_EXIT", [ RTEMS_RECORD_THREAD_EXITTED ] = "THREAD_EXITTED", [ RTEMS_RECORD_THREAD_ID ] = "THREAD_ID", + [ RTEMS_RECORD_THREAD_NAME ] = "THREAD_NAME", [ RTEMS_RECORD_THREAD_PRIO_CURRENT_HIGH ] = "THREAD_PRIO_CURRENT_HIGH", [ RTEMS_RECORD_THREAD_PRIO_CURRENT_LOW ] = "THREAD_PRIO_CURRENT_LOW", [ RTEMS_RECORD_THREAD_PRIO_REAL_HIGH ] = "THREAD_PRIO_REAL_HIGH", @@ -550,7 +551,6 @@ static const char * const event_text[] = { [ RTEMS_RECORD_SYSTEM_508 ] = "SYSTEM_508", [ RTEMS_RECORD_SYSTEM_509 ] = "SYSTEM_509", [ RTEMS_RECORD_SYSTEM_510 ] = "SYSTEM_510", - [ RTEMS_RECORD_SYSTEM_511 ] = "SYSTEM_511", [ RTEMS_RECORD_USER_0 ] = "USER_0", [ RTEMS_RECORD_USER_1 ] = "USER_1", [ RTEMS_RECORD_USER_2 ] = "USER_2", diff --git a/cpukit/libtrace/record/record-userext.c b/cpukit/libtrace/record/record-userext.c index a57a3f751e..ff448e5573 100644 --- a/cpukit/libtrace/record/record-userext.c +++ b/cpukit/libtrace/record/record-userext.c @@ -30,17 +30,43 @@ #endif #include -#include +#include bool _Record_Thread_create( struct _Thread_Control *executing, struct _Thread_Control *created ) { - rtems_record_produce( - RTEMS_RECORD_THREAD_CREATE, - created->Object.id - ); + rtems_record_data data; + char name[ 2 * THREAD_DEFAULT_MAXIMUM_NAME_SIZE ]; + rtems_record_item items[ 1 + sizeof( name ) / sizeof( data ) ]; + size_t n; + size_t i; + size_t j; + + i = 0; + items[ i ].event = RTEMS_RECORD_THREAD_CREATE; + items[ i ].data = created->Object.id; + + n = _Thread_Get_name( created, name, sizeof( name ) ); + j = 0; + + while ( j < n ) { + size_t k; + + data = 0; + + for ( k = 0; j < n && k < sizeof( data ); ++k ) { + data = ( data << 8 ) | name[ j ]; + ++j; + } + + ++i; + items[ i ].event = RTEMS_RECORD_THREAD_NAME; + items[ i ].data = data; + } + + rtems_record_produce_n( items, i + 1 ); return true; } diff --git a/testsuites/libtests/record01/init.c b/testsuites/libtests/record01/init.c index 3a3680c292..fdc2a859a8 100644 --- a/testsuites/libtests/record01/init.c +++ b/testsuites/libtests/record01/init.c @@ -151,6 +151,31 @@ static const rtems_record_item expected_items_12[] = { { .event = TE(44, UE(43)), .data = 45 } }; +#ifdef RTEMS_NETWORKING +static const rtems_record_item expected_items_13[] = { + { .event = TE(0, RTEMS_RECORD_THREAD_ID), .data = 0x9010001 }, + { + .event = TE(0, RTEMS_RECORD_THREAD_NAME), + .data = rtems_build_name('I', 'D', 'L', 'E') + }, + { .event = TE(0, RTEMS_RECORD_THREAD_ID), .data = 0xa010001 }, + { + .event = TE(0, RTEMS_RECORD_THREAD_NAME), + .data = rtems_build_name('U', 'I', '1', ' ') + }, + { .event = TE(0, RTEMS_RECORD_THREAD_ID), .data = 0xa010002 }, + { + .event = TE(0, RTEMS_RECORD_THREAD_NAME), + .data = rtems_build_name('n', 't', 'w', 'k') + }, + { .event = TE(0, RTEMS_RECORD_THREAD_ID), .data = 0xa010003 }, + { + .event = TE(0, RTEMS_RECORD_THREAD_NAME), + .data = rtems_build_name('R', 'C', 'R', 'D') + } +}; +#endif + static void init_context(test_context *ctx) { memset(ctx, 0, sizeof(*ctx)); @@ -521,6 +546,7 @@ static int connect_client(void) ssize_t n; uint32_t v; rtems_record_item item; + rtems_record_item items[8]; fd = socket(PF_INET, SOCK_STREAM, 0); rtems_test_assert(fd >= 0); @@ -560,6 +586,12 @@ static int connect_client(void) rtems_test_assert(item.event == TE(0, RTEMS_RECORD_FREQUENCY)); rtems_test_assert(item.data == rtems_counter_frequency()); + n = read(fd, items, sizeof(expected_items_13)); + rtems_test_assert(n == (ssize_t) sizeof(expected_items_13)); + rtems_test_assert( + memcmp(items, expected_items_13, sizeof(expected_items_13)) == 0 + ); + return fd; } -- cgit v1.2.3