summaryrefslogtreecommitdiffstats
path: root/trace/record/record-main-lttng.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace/record/record-main-lttng.c')
-rw-r--r--trace/record/record-main-lttng.c585
1 files changed, 0 insertions, 585 deletions
diff --git a/trace/record/record-main-lttng.c b/trace/record/record-main-lttng.c
deleted file mode 100644
index 3aeafab..0000000
--- a/trace/record/record-main-lttng.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2019 Ravindra Kumar Meena <rmeena840@gmail.com>
- * Copyright (C) 2018, 2019 embedded brains GmbH
- *
- * 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.
- */
-
-#include <rtems/recorddata.h>
-#include <rtems/recordclient.h>
-
-#include <sys/queue.h>
-#include <sys/socket.h>
-
-#include <assert.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define CTF_MAGIC 0xC1FC1FC1
-#define TASK_RUNNING 0x0000
-#define TASK_IDLE 0x0402
-#define UUID_SIZE 16
-#define THREAD_NAME_SIZE 16
-#define THREAD_API_COUNT 3
-#define THREAD_ID_COUNT 0x10000
-#define BITS_PER_CHAR 8
-#define COMPACT_HEADER_ID 31
-
-static const struct option longopts[] = {
- { "help", 0, NULL, 'h' },
- { "host", 1, NULL, 'H' },
- { "port", 1, NULL, 'p' },
- { "input", 1, NULL, 'i' },
- { NULL, 0, NULL, 0 }
-};
-
-typedef struct {
- uint64_t ns;
- uint32_t cpu;
- rtems_record_event event;
- uint64_t data;
-} client_item;
-
-typedef struct {
- uint32_t ctf_magic;
- uint8_t uuid[ UUID_SIZE ];
- uint32_t stream_id;
- uint64_t stream_instance_id;
-} __attribute__((__packed__)) packet_header;
-
-typedef struct packet_context {
- packet_header header;
- uint64_t timestamp_begin;
- uint64_t timestamp_end;
- uint64_t content_size;
- uint64_t packet_size;
- uint64_t packet_seq_num;
- unsigned long events_discarded;
- uint32_t cpu_id;
-} __attribute__((__packed__)) packet_context;
-
-typedef struct {
- uint8_t id;
- uint32_t event_id;
- uint64_t ns;
-} __attribute__((__packed__)) event_header_compact;
-
-typedef struct {
- event_header_compact header;
- uint8_t prev_comm[ THREAD_NAME_SIZE ];
- int32_t prev_tid;
- int32_t prev_prio;
- int64_t prev_state;
- uint8_t next_comm[ THREAD_NAME_SIZE ];
- int32_t next_tid;
- int32_t next_prio;
-} __attribute__((__packed__)) sched_switch;
-
-typedef struct {
- FILE *event_stream;
- uint64_t timestamp_begin;
- uint64_t timestamp_end;
- uint64_t content_size;
- uint64_t packet_size;
- uint32_t thread_id;
- uint64_t thread_ns;
- size_t thread_name_index;
- sched_switch sched_switch;
-} per_cpu_context;
-
-typedef struct {
- rtems_record_client_context base;
- per_cpu_context per_cpu[ RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT ];
-
- /*
- * @brief Thread names indexed by API and object index.
- *
- * The API indices are 0 for Internal API, 1 for Classic API and 2 for
- * POSIX API.
- */
- char thread_names[ THREAD_API_COUNT ][ THREAD_ID_COUNT ][ THREAD_NAME_SIZE ];
-} client_context;
-
-static const char empty_thread_name[ THREAD_API_COUNT ];
-
-static const uint8_t uuid[] = { 0x6a, 0x77, 0x15, 0xd0, 0xb5, 0x02, 0x4c, 0x65,
-0x86, 0x78, 0x67, 0x77, 0xac, 0x7f, 0x75, 0x5a };
-
-static void usage( char **argv )
-{
- printf(
- "%s [--host=HOST] [--port=PORT] [--input=INPUT]\n"
- "\n"
- "Mandatory arguments to long options are mandatory for short options too.\n"
- " -h, --help print this help text\n"
- " -H, --host=HOST the host IPv4 address of the record server\n"
- " -p, --port=PORT the TCP port of the record server\n"
- " -i, --input=INPUT the input file\n",
- argv[ 0 ]
- );
-}
-
-static int connect_client(
- const char *host,
- uint16_t port,
- const char *input_file,
- bool input_file_flag
-)
-{
- struct sockaddr_in in_addr;
- int fd;
- int rv;
-
- fd = ( input_file_flag ) ? open( input_file, O_RDONLY ) :
- socket( PF_INET, SOCK_STREAM, 0 );
- assert( fd >= 0 );
-
- memset( &in_addr, 0, sizeof( in_addr ) );
- in_addr.sin_family = AF_INET;
- in_addr.sin_port = htons( port );
- in_addr.sin_addr.s_addr = inet_addr( host );
-
- if ( !input_file_flag ) {
- rv = connect( fd, ( struct sockaddr * ) &in_addr, sizeof( in_addr ) );
- assert( rv == 0 );
- }
-
- return fd;
-}
-
-static uint32_t get_api_index_of_id( uint32_t id )
-{
- return ( ( id >> 24 ) & 0x7 ) - 1;
-}
-
-static uint32_t get_obj_index_of_id( uint32_t id )
-{
- return id & ( THREAD_ID_COUNT - 1 );
-}
-
-static bool is_idle_task_by_api_index( uint32_t api_index )
-{
- return api_index == 0;
-}
-
-static void copy_thread_name(
- const client_context *ctx,
- const client_item *item,
- size_t api_index,
- uint8_t *dst
-)
-{
- const char *name;
-
- if ( api_index < THREAD_API_COUNT ) {
- name = ctx->thread_names[ api_index ][ get_obj_index_of_id( item->data ) ];
- } else {
- name = empty_thread_name;
- }
-
- memcpy( dst, name, THREAD_NAME_SIZE );
-
- if ( is_idle_task_by_api_index( api_index ) ) {
- /*
- * In Linux, the idle threads are bound to a specific CPU (swapper/n). In
- * RTEMS, the idle threads can move around, so mimic this Linux behaviour.
- */
- snprintf(
- (char *) dst + 4,
- THREAD_NAME_SIZE - 4,
- "/%lu",
- (unsigned long) item->cpu
- );
- }
-}
-
-static void write_sched_switch(
- client_context *ctx,
- per_cpu_context *pcpu,
- const client_item *item
-)
-{
- size_t se_size;
- sched_switch *se;
- uint32_t api_index;
-
- se_size = sizeof( sched_switch ) * BITS_PER_CHAR;
- pcpu->content_size += se_size;
- pcpu->packet_size += se_size;
-
- api_index = get_api_index_of_id( item->data );
- se = &pcpu->sched_switch;
-
- se->header.id = COMPACT_HEADER_ID;
- se->header.event_id = 0;
- se->header.ns = item->ns;
- se->next_tid = is_idle_task_by_api_index( api_index ) ? 0 : item->data;
-
- copy_thread_name( ctx, item, api_index, se->next_comm );
- fwrite( se, sizeof( *se ), 1, pcpu->event_stream );
-}
-
-static void add_thread_name(
- client_context *ctx,
- per_cpu_context *pcpu,
- const client_item *item
-)
-{
- uint64_t name;
- uint32_t api_index;
- uint32_t obj_index;
- size_t i;
-
- if ( pcpu->thread_name_index >= THREAD_NAME_SIZE ) {
- return;
- }
-
- api_index = get_api_index_of_id( pcpu->thread_id );
-
- if ( api_index >= THREAD_API_COUNT ) {
- return;
- }
-
- obj_index = get_obj_index_of_id( pcpu->thread_id );
- name = item->data;
-
- for (
- i = pcpu->thread_name_index;
- i < pcpu->thread_name_index + ctx->base.data_size;
- ++i
- ) {
- ctx->thread_names[ api_index ][ obj_index ][ i ] = (char) name;
- name >>= BITS_PER_CHAR;
- }
-
- pcpu->thread_name_index = i;
-}
-
-static void print_item( client_context *ctx, const client_item *item )
-{
- per_cpu_context *pcpu;
- sched_switch *se;
- uint32_t api_index;
-
- pcpu = &ctx->per_cpu[ item->cpu ];
- se = &pcpu->sched_switch;
-
- if ( pcpu->timestamp_begin == 0 ) {
- pcpu->timestamp_begin = item->ns;
- }
-
- pcpu->timestamp_end = item->ns;
-
- switch ( item->event ) {
- case RTEMS_RECORD_THREAD_SWITCH_OUT:
- api_index = get_api_index_of_id( item->data );
- se->header.ns = item->ns;
-
- if ( is_idle_task_by_api_index( api_index ) ) {
- se->prev_tid = 0;
- se->prev_state = TASK_IDLE;
- } else {
- se->prev_tid = item->data;
- se->prev_state = TASK_RUNNING;
- }
-
- copy_thread_name( ctx, item, api_index, se->prev_comm );
- break;
- case RTEMS_RECORD_THREAD_SWITCH_IN:
- if ( item->ns == se->header.ns ) {
- write_sched_switch( ctx, pcpu, item );
- }
- break;
- case RTEMS_RECORD_THREAD_ID:
- pcpu->thread_id = item->data;
- pcpu->thread_ns = item->ns;
- pcpu->thread_name_index = 0;
- break;
- case RTEMS_RECORD_THREAD_NAME:
- add_thread_name( ctx, pcpu, item );
- break;
- default:
- break;
- }
-}
-
-static rtems_record_client_status handler(
- uint64_t bt,
- uint32_t cpu,
- rtems_record_event event,
- uint64_t data,
- void *arg
-)
-{
- client_item item;
-
- item.ns = rtems_record_client_bintime_to_nanoseconds( bt );
- item.cpu = cpu;
- item.event = event;
- item.data = data;
-
- print_item( arg, &item );
-
- return RTEMS_RECORD_CLIENT_SUCCESS;
-}
-
-static const char metadata[] =
-"/* CTF 1.8 */\n"
-"\n"
-"typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
-"typealias integer { size = 8; align = 8; signed = false; } := uint8_t;\n"
-"typealias integer { size = 32; align = 8; signed = false; } := uint32_t;\n"
-"typealias integer { size = 64; align = 8; signed = false; } := uint64_t;\n"
-"typealias integer { size = 64; align = 8; signed = false; } := unsigned long;\n"
-"\n"
-"trace {\n"
-"\tmajor = 1;\n"
-"\tminor = 8;\n"
-"\tuuid = \"6a7715d0-b502-4c65-8678-6777ac7f755a\";\n"
-"\tbyte_order = le;\n"
-"\tpacket.header := struct {\n"
-"\t\tuint32_t magic;\n"
-"\t\tuint8_t uuid[16];\n"
-"\t\tuint32_t stream_id;\n"
-"\t\tuint64_t stream_instance_id;\n"
-"\t};\n"
-"};\n"
-"\n"
-"env {\n"
-"\thostname = \"Record_Item\";\n"
-"\tdomain = \"kernel\";\n"
-"\tsysname = \"Linux\";\n"
-"\tkernel_release = \"4.18.14-arch1-1-ARCH\";\n"
-"\tkernel_version = \"#1 SMP PREEMPT Sat Thu 17 13:42:37 UTC 2019\";\n"
-"\ttracer_name = \"lttng-modules\";\n"
-"\ttracer_major = 2;\n"
-"\ttracer_minor = 11;\n"
-"\ttracer_patchlevel = 0;\n"
-"};\n"
-"\n"
-"clock {\n"
-"\tname = \"monotonic\";\n"
-"\tuuid = \"234d669d-7651-4bc1-a7fd-af581ecc6232\";\n"
-"\tdescription = \"Monotonic Clock\";\n"
-"\tfreq = 1000000000;\n"
-"\toffset = 1539783991179109789;\n"
-"};\n"
-"\n"
-"typealias integer {\n"
-"\tsize = 27; align = 1; signed = false;\n"
-"\tmap = clock.monotonic.value;\n"
-"} := uint27_clock_monotonic_t;\n"
-"\n"
-"typealias integer {\n"
-"\tsize = 64; align = 8; signed = false;\n"
-"\tmap = clock.monotonic.value;\n"
-"} := uint64_clock_monotonic_t;\n"
-"\n"
-"struct packet_context {\n"
-"\tuint64_clock_monotonic_t timestamp_begin;\n"
-"\tuint64_clock_monotonic_t timestamp_end;\n"
-"\tuint64_t content_size;\n"
-"\tuint64_t packet_size;\n"
-"\tuint64_t packet_seq_num;\n"
-"\tunsigned long events_discarded;\n"
-"\tuint32_t cpu_id;\n"
-"};\n"
-"\n"
-"struct event_header_compact {\n"
-"\tenum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
-"\tvariant <id> {\n"
-"\t\tstruct {\n"
-"\t\t\tuint27_clock_monotonic_t timestamp;\n"
-"\t\t} compact;\n"
-"\t\tstruct {\n"
-"\t\t\tuint32_t id;\n"
-"\t\t\tuint64_clock_monotonic_t timestamp;\n"
-"\t\t} extended;\n"
-"\t} v;\n"
-"} align(8);\n"
-"\n"
-"stream {\n"
-"\tid = 0;\n"
-"\tevent.header := struct event_header_compact;\n"
-"\tpacket.context := struct packet_context;\n"
-"};\n"
-"\n"
-"event {\n"
-"\tname = \"sched_switch\";\n"
-"\tid = 0;\n"
-"\tstream_id = 0;\n"
-"\tfields := struct {\n"
-"\t\tinteger { size = 8; align = 8; signed = 0; encoding = UTF8; base = 10;}\
- _prev_comm[16];\n"
-"\t\tinteger { size = 32; align = 8; signed = 1; encoding = none; base = 10; }\
- _prev_tid;\n"
-"\t\tinteger { size = 32; align = 8; signed = 1; encoding = none; base = 10; }\
- _prev_prio;\n"
-"\t\tinteger { size = 64; align = 8; signed = 1; encoding = none; base = 10; }\
- _prev_state;\n"
-"\t\tinteger { size = 8; align = 8; signed = 0; encoding = UTF8; base = 10; }\
- _next_comm[16];\n"
-"\t\tinteger { size = 32; align = 8; signed = 1; encoding = none; base = 10; }\
- _next_tid;\n"
-"\t\tinteger { size = 32; align = 8; signed = 1; encoding = none; base = 10; }\
- _next_prio;\n"
-"\t};\n"
-"};"
-;
-
-static void generate_metadata()
-{
- FILE *file = fopen( "metadata", "w" );
- assert( file != NULL );
- fwrite( metadata, sizeof( metadata ) - 1, 1, file );
- fclose( file );
-}
-
-int main( int argc, char **argv )
-{
- client_context ctx;
- packet_context pkt_ctx;
- size_t pkt_ctx_size;
- const char *host;
- uint16_t port;
- const char *input_file;
- bool input_file_flag;
- bool input_TCP_host;
- bool input_TCP_port;
- int fd;
- int rv;
- int opt;
- int longindex;
- size_t i;
- char filename[ 256 ];
-
- host = "127.0.0.1";
- port = 1234;
- input_file = "raw_data";
- input_file_flag = false;
- input_TCP_host = false;
- input_TCP_port = false;
-
- while (
- ( opt = getopt_long( argc, argv, "hH:p:i:", &longopts[0], &longindex ) )
- != -1
- ) {
- switch ( opt ) {
- case 'h':
- usage( argv );
- exit( EXIT_SUCCESS );
- break;
- case 'H':
- host = optarg;
- input_TCP_host = true;
- break;
- case 'p':
- port = (uint16_t) strtoul( optarg, NULL, 10 );
- input_TCP_port = true;
- break;
- case 'i':
- input_file = optarg;
- assert( input_file != NULL );
- input_file_flag = true;
- break;
- default:
- exit( EXIT_FAILURE );
- break;
- }
- }
-
- if( input_file_flag && ( input_TCP_host || input_TCP_port ) ) {
- printf( "There should be one input medium\n" );
- exit( EXIT_SUCCESS );
- }
-
- memset( &ctx, 0, sizeof( ctx ) );
-
- generate_metadata();
-
- memset( &pkt_ctx, 0, sizeof( pkt_ctx ) );
- memcpy( pkt_ctx.header.uuid, uuid, sizeof( pkt_ctx.header.uuid ) );
- pkt_ctx.header.ctf_magic = CTF_MAGIC;
-
- for ( i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i ) {
- FILE *f;
-
- snprintf( filename, sizeof( filename ), "event_%zu", i );
- f = fopen( filename, "wb" );
- assert( f != NULL );
- ctx.per_cpu[ i ].event_stream = f;
- fwrite( &pkt_ctx, sizeof( pkt_ctx ), 1, f );
- }
-
- fd = connect_client( host, port, input_file, input_file_flag );
- rtems_record_client_init( &ctx.base, handler, &ctx );
-
- while ( true ) {
- int buf[ 8192 ];
- ssize_t n;
-
- n = ( input_file_flag ) ? read( fd, buf, sizeof( buf ) ) :
- recv( fd, buf, sizeof( buf ), 0 );
- if ( n > 0 ) {
- rtems_record_client_run( &ctx.base, buf, (size_t) n );
- } else {
- break;
- }
- }
-
- rtems_record_client_destroy( &ctx.base );
- pkt_ctx_size = sizeof( pkt_ctx ) * BITS_PER_CHAR;
-
- for ( i = 0; i < RTEMS_RECORD_CLIENT_MAXIMUM_CPU_COUNT; ++i ) {
- per_cpu_context *pcpu;
-
- pcpu = &ctx.per_cpu[ i ];
- fseek( pcpu->event_stream, 0, SEEK_SET );
-
- pkt_ctx.header.stream_instance_id = i;
- pkt_ctx.timestamp_begin = pcpu->timestamp_begin;
- pkt_ctx.timestamp_end = pcpu->timestamp_end;
- pkt_ctx.content_size = pcpu->content_size + pkt_ctx_size;
- pkt_ctx.packet_size = pcpu->packet_size + pkt_ctx_size;
- pkt_ctx.cpu_id = i;
-
- fwrite( &pkt_ctx, sizeof( pkt_ctx ), 1, pcpu->event_stream );
- fclose( pcpu->event_stream );
- }
-
- rv = close( fd );
- assert( rv == 0 );
-
- return 0;
-}