I was reviewing this code and lost my spot. There are some notes below, but I have no more time to weed through. I'd recommend splitting this patch into more pieces: 1) Moving code into capture_support. 2) Adding SMP support. 3) Fixing formatting/style/documentation issues in legacy portions.
Currently there are a mix of the three, and it makes reviewing the changes quite complex. Anyway, there are some other notes below. On Tue, Nov 4, 2014 at 8:39 AM, Jennifer Averett <jennifer.aver...@oarcorp.com> wrote: > To support smp data was broken into global and percpu capture data. > Capture control must be disabled prior to printing or setting of > watch points. > > Methods to print the data were moved from capture-cli into > a support area and are no longer static so that they can > be shared by test routines, or application code that wants > to use the capture engine without the shell interface. > --- > cpukit/libmisc/Makefile.am | 1 + > cpukit/libmisc/capture/capture-cli.c | 221 +------------ > cpukit/libmisc/capture/capture-cli.h | 4 +- > cpukit/libmisc/capture/capture.c | 411 > +++++++++++++----------- > cpukit/libmisc/capture/capture.h | 82 ++--- > cpukit/libmisc/capture/capture_buffer.c | 6 +- > cpukit/libmisc/capture/capture_buffer.h | 6 +- > cpukit/libmisc/capture/capture_support.c | 307 ++++++++++++++++++ > cpukit/libmisc/capture/capture_user_extension.c | 17 +- > cpukit/libmisc/capture/captureimpl.h | 102 ++++-- > 10 files changed, 667 insertions(+), 490 deletions(-) > create mode 100644 cpukit/libmisc/capture/capture_support.c > > diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am > index 021a251..352379d 100644 > --- a/cpukit/libmisc/Makefile.am > +++ b/cpukit/libmisc/Makefile.am > @@ -19,6 +19,7 @@ EXTRA_DIST += capture/README > noinst_LIBRARIES += libcapture.a > libcapture_a_SOURCES = capture/capture.c capture/capture-cli.c \ > capture/capture_user_extension.c capture/capture_buffer.c \ > + capture/capture_support.c \ > capture/capture.h capture/captureimpl.h capture/capture-cli.h \ > capture/capture_buffer.h > > diff --git a/cpukit/libmisc/capture/capture-cli.c > b/cpukit/libmisc/capture/capture-cli.c > index ad53ccc..595c9cf 100644 > --- a/cpukit/libmisc/capture/capture-cli.c > +++ b/cpukit/libmisc/capture/capture-cli.c > @@ -5,7 +5,7 @@ > All rights reserved Objective Design Systems Pty Ltd, 2002 > Chris Johns (c...@acm.org) > > - COPYRIGHT (c) 1989-1998. > + COPYRIGHT (c) 1989-2014. > On-Line Applications Research Corporation (OAR). > > The license and distribution terms for this file may be > @@ -41,6 +41,13 @@ > > #define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (20) > > +typedef struct { > + rtems_capture_record_t* rec; > + uint32_t read; > + uint32_t last_t; > + uint32_t printed; > +} ctrace_per_cpu_t; > + This does not seem to belong here. > /* > * Counter used to count the number of active tasks. > */ > @@ -209,31 +216,6 @@ rtems_capture_cli_disable (int > argc RC_UNUSED, > fprintf (stdout, "capture engine disabled.\n"); > } > > -/* > - * rtems_catpure_cli_print_uptime > - * > - * DESCRIPTION: > - * > - * This function prints the nanosecond uptime to stdout. > - */ > -static void > -rtems_capture_cli_print_timestamp (uint64_t uptime) > -{ > - uint32_t hours; > - uint32_t minutes; > - uint32_t seconds; > - uint32_t nanosecs; > - > - seconds = uptime / 1000000000LLU; > - minutes = seconds / 60; > - hours = minutes / 60; > - minutes = minutes % 60; > - seconds = seconds % 60; > - nanosecs = uptime % 1000000000; > - > - fprintf (stdout, "%5lu:%02lu:%02lu.%09lu", hours, minutes, seconds, > nanosecs); > -} > - > static void > rtems_capture_cli_print_task (rtems_tcb *tcb) > { > @@ -273,47 +255,6 @@ rtems_capture_cli_print_task (rtems_tcb *tcb) > } > fprintf (stdout, "\n"); > } > -static void > -rtems_caputure_cli_print_record_std(rtems_capture_record_t* rec, uint64_t > diff) > -{ > - uint32_t event; > - int e; > - > - event = rec->events >> RTEMS_CAPTURE_EVENT_START; > - > - for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++) > - { > - if (event & 1) > - { > - rtems_capture_cli_print_timestamp (rec->time); > - fprintf (stdout, " %9" PRId64 " ", diff); > - rtems_monitor_dump_id (rec->task_id); > - fprintf(stdout, " %3" PRId32 " %3" PRId32 " %s\n", > - (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, > - (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, > - rtems_capture_event_text (e)); > - } > - event >>= 1; > - } > -} > - > -static void > -rtems_caputre_cli_print_record_task(rtems_capture_record_t* rec) > -{ > - rtems_capture_task_record_t* task_rec = (rtems_capture_task_record_t*) rec; > - > - rtems_capture_cli_print_timestamp (rec->time); > - fprintf (stdout, " "); > - rtems_monitor_dump_id (rec->task_id); > - fprintf (stdout, " %c%c%c%c", > - (char) (task_rec->name >> 24) & 0xff, > - (char) (task_rec->name >> 16) & 0xff, > - (char) (task_rec->name >> 8) & 0xff, > - (char) (task_rec->name >> 0) & 0xff); > - fprintf (stdout, " %3" PRId32 " %3" PRId32 "\n", > - task_rec->start_priority, > - task_rec->stack_size); > -} > > /* > * rtems_capture_cli_count_tasks > @@ -355,7 +296,7 @@ rtems_capture_cli_task_list (int > argc RC_UNUSED, > rtems_iterate_over_all_threads (rtems_capture_cli_count_tasks); > > fprintf (stdout, "uptime: "); > - rtems_capture_cli_print_timestamp (uptime); > + rtems_capture_print_timestamp (uptime); > fprintf (stdout, "\ntotal %i\n", rtems_capture_cli_task_count); > rtems_iterate_over_all_threads (rtems_capture_cli_print_task); > } > @@ -375,79 +316,7 @@ rtems_capture_cli_watch_list (int > argc RC_UNUSED, > const rtems_monitor_command_arg_t* command_arg > RC_UNUSED, > bool verbose > RC_UNUSED) > { > - rtems_capture_control_t* control = rtems_capture_get_control_list (); > - rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); > - rtems_task_priority floor = rtems_capture_watch_get_floor (); > - > - fprintf (stdout, "watch priority ceiling is %" PRId32 "\n", ceiling); > - fprintf (stdout, "watch priority floor is %" PRId32 "\n", floor); > - fprintf (stdout, "global watch is %s\n", > - rtems_capture_watch_global_on () ? "enabled" : "disabled"); > - fprintf (stdout, "total %" PRId32 "\n", rtems_capture_control_count ()); > - > - while (control) > - { > - uint32_t flags; > - int f; > - int fshowed; > - int lf; > - > - fprintf (stdout, " "); > - rtems_monitor_dump_id (rtems_capture_control_id (control)); > - fprintf (stdout, " "); > - rtems_monitor_dump_name (rtems_capture_control_name (control)); > - flags = rtems_capture_control_flags (control); > - fprintf (stdout, " %c%c ", > - rtems_capture_watch_global_on () ? 'g' : '-', > - flags & RTEMS_CAPTURE_WATCH ? 'w' : '-'); > - flags = rtems_capture_control_to_triggers (control); > - fprintf (stdout, " T:%c%c%c%c%c%c%c", > - flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > - flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > - flags & RTEMS_CAPTURE_START ? 'S' : '-', > - flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > - flags & RTEMS_CAPTURE_DELETE ? 'D' : '-', > - flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-', > - flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-'); > - flags = rtems_capture_control_from_triggers (control); > - fprintf (stdout, " F:%c%c%c%c%c", > - flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > - flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > - flags & RTEMS_CAPTURE_START ? 'S' : '-', > - flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > - flags & RTEMS_CAPTURE_DELETE ? 'D' : '-'); > - > - for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++) > - { > - if (rtems_capture_control_by_valid (control, f)) > - { > - if (lf && ((fshowed % 3) == 0)) > - { > - fprintf (stdout, "\n"); > - lf = 0; > - } > - > - fprintf (stdout, " %2i:", f); > - rtems_monitor_dump_name (rtems_capture_control_by_name (control, f)); > - fprintf (stdout, "/"); > - rtems_monitor_dump_id (rtems_capture_control_by_id (control, f)); > - flags = rtems_capture_control_by_triggers (control, f); > - fprintf (stdout, ":%c%c%c%c%c", > - flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > - flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > - flags & RTEMS_CAPTURE_START ? 'S' : '-', > - flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > - flags & RTEMS_CAPTURE_DELETE ? 'D' : '-'); > - fshowed++; > - lf = 1; > - } > - } > - > - if (lf) > - fprintf (stdout, "\n"); > - > - control = rtems_capture_next_control (control); > - } > + rtems_capture_print_watch_list(); > } > > /* > @@ -1154,16 +1023,9 @@ rtems_capture_cli_trace_records (int > argc, > const rtems_monitor_command_arg_t* > command_arg RC_UNUSED, > bool verbose > RC_UNUSED) > { > - rtems_status_code sc; > bool csv = false; > static int dump_total = 22; > - int total; > - int count; > - uint32_t read; > - rtems_capture_record_t* rec; > - uint8_t* ptr; > int arg; > - rtems_capture_time_t last_t = 0; > > for (arg = 1; arg < argc; arg++) > { > @@ -1192,68 +1054,7 @@ rtems_capture_cli_trace_records (int > argc, > } > } > > - total = dump_total; > - > - while (total) > - { > - sc = rtems_capture_read (0, 0, &read, &rec); > - > - if (sc != RTEMS_SUCCESSFUL) > - { > - fprintf (stdout, "error: trace read failed: %s\n", rtems_status_text > (sc)); > - rtems_capture_flush (0); > - return; > - } > - > - /* > - * If we have no records then just exist. We still need to release > - * the reader lock. > - */ > - > - if (read == 0) > - { > - rtems_capture_release (read); > - break; > - } > - > - count = total < read ? total : read; > - ptr = (uint8_t *) rec; > - while (count--) > - { > - rec = (rtems_capture_record_t*) ptr; > - > - if (csv) > - fprintf (stdout, "%08" PRIu32 ",%03" PRIu32 > - ",%03" PRIu32 ",%04" PRIx32 ",%" PRId64 "\n", > - rec->task_id, > - (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, > - (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, > - (rec->events >> RTEMS_CAPTURE_EVENT_START), > - (uint64_t) rec->time); > - else { > - if ((rec->events >> RTEMS_CAPTURE_EVENT_START) == 0) > - rtems_caputre_cli_print_record_task( rec ); > - else { > - uint64_t diff = 0; > - if (last_t) > - diff = rec->time - last_t; > - last_t = rec->time; > - > - rtems_caputure_cli_print_record_std( rec, diff ); > - } > - } > - ptr += rec->size; > - } > - > - count = total < read ? total : read; > - > - if (count < total) > - total -= count; > - else > - total = 0; > - > - rtems_capture_release (count); > - } > + rtems_capture_print_trace_records( dump_total, csv ); > } > > /* > diff --git a/cpukit/libmisc/capture/capture-cli.h > b/cpukit/libmisc/capture/capture-cli.h > index 8f97522..4fa2a4a 100644 > --- a/cpukit/libmisc/capture/capture-cli.h > +++ b/cpukit/libmisc/capture/capture-cli.h > @@ -12,7 +12,7 @@ > All rights reserved Objective Design Systems Pty Ltd, 2002 > Chris Johns (c...@acm.org) > > - COPYRIGHT (c) 1989-1998. > + COPYRIGHT (c) 1989-2014. > On-Line Applications Research Corporation (OAR). > > The license and distribution terms for this file may be > @@ -36,7 +36,7 @@ > extern "C" { > #endif > > -#include <rtems/capture.h> > +#include <rtems/captureimpl.h> > Is capture-cli.h included by users? If so, it should not be "leaking" captureimpl.h. > /** > * rtems_capture_cli_init > diff --git a/cpukit/libmisc/capture/capture.c > b/cpukit/libmisc/capture/capture.c > index a83bc90..a0a2089 100644 > --- a/cpukit/libmisc/capture/capture.c > +++ b/cpukit/libmisc/capture/capture.c > @@ -5,7 +5,7 @@ > All rights reserved Objective Design Systems Pty Ltd, 2002 > Chris Johns (c...@acm.org) > > - COPYRIGHT (c) 1989-2009. > + COPYRIGHT (c) 1989-2014. > On-Line Applications Research Corporation (OAR). > > The license and distribution terms for this file may be > @@ -59,21 +59,52 @@ > #define RTEMS_CAPTURE_RECORD_EVENTS (0) > #endif > > +typedef struct { > + rtems_capture_buffer_t records; > + uint32_t count; > + rtems_id reader; > + rtems_interrupt_lock lock; > + uint32_t flags; > +} rtems_capture_per_cpu_data_t; > + > +typedef struct { > + uint32_t flags; > + rtems_capture_control_t* controls; > + int extension_index; > + rtems_capture_timestamp timestamp; > + rtems_task_priority ceiling; > + rtems_task_priority floor; > + rtems_interrupt_lock lock; > +} rtems_capture_global_data_t; > + I'd suggest cleaning up the typedefs to remove the _t specifier. We should not be declaring such types in RTEMS that are not POSIX types. (Though these are not so bad as they are local to this C file, and not leaked through a header, we should still discourage the practice.) > +static rtems_capture_per_cpu_data_t *capture_per_cpu = NULL; > + > +static rtems_capture_global_data_t capture_global; > > /* > * RTEMS Capture Data. > */ > -static rtems_capture_buffer_t capture_records = {NULL, 0, 0, 0, 0, 0}; > -static uint32_t capture_count; > -static uint32_t capture_flags; > -static rtems_capture_control_t* capture_controls; > -static int capture_extension_index; > -static rtems_capture_timestamp capture_timestamp; > -static rtems_task_priority capture_ceiling; > -static rtems_task_priority capture_floor; > -static rtems_id capture_reader; > -static rtems_interrupt_lock capture_lock = > - RTEMS_INTERRUPT_LOCK_INITIALIZER("capture"); > +#define capture_per_cpu_get( _cpu ) \ > + ( &capture_per_cpu[ _cpu ] ) > + > +#define capture_records_on_cpu( _cpu ) capture_per_cpu[ _cpu ].records > +#define capture_count_on_cpu( _cpu ) capture_per_cpu[ _cpu ].count > +#define capture_flags_on_cpu( _cpu ) capture_per_cpu[ _cpu ].flags > +#define capture_reader_on_cpu( _cpu ) capture_per_cpu[ _cpu ].reader > +#define capture_lock_on_cpu( _cpu ) capture_per_cpu[ _cpu ].lock > + > +#define capture_records capture_records_on_cpu( > _SMP_Get_current_processor() ) > +#define capture_count capture_count_on_cpu( > _SMP_Get_current_processor() ) > +#define capture_flags_per_cpu capture_flags_on_cpu( > _SMP_Get_current_processor() ) > +#define capture_flags_global capture_global.flags > +#define capture_controls capture_global.controls > +#define capture_extension_index capture_global.extension_index > +#define capture_timestamp capture_global.timestamp > +#define capture_ceiling capture_global.ceiling > +#define capture_floor capture_global.floor > +#define capture_reader capture_reader_on_cpu( > _SMP_Get_current_processor() ) > +#define capture_lock_per_cpu capture_lock_on_cpu( > _SMP_Get_current_processor() ) > +#define capture_lock_global capture_global.lock > Why not define capture_lock? > /* > * RTEMS Event text. > @@ -108,12 +139,12 @@ int rtems_capture_get_extension_index(void) > > uint32_t rtems_capture_get_flags(void) > { > - return capture_flags; > + return capture_flags_global; > } > > void rtems_capture_set_flags(uint32_t mask) > { > - capture_flags |= mask; > + capture_flags_global |= mask; > } > > /* > @@ -284,11 +315,11 @@ rtems_capture_create_control (rtems_name name, rtems_id > id) > > if (control == NULL) > { > - bool ok = rtems_workspace_allocate (sizeof (*control), (void **) > &control); > + control = malloc( sizeof (*control)); > These functional changes would be better presented as a separate commit if that makes sense. Was it agreed that replacing the workspace_allocate() with malloc() is OK here? > - if (!ok) > + if (!control) > { > - capture_flags |= RTEMS_CAPTURE_NO_MEMORY; > + capture_flags_global |= RTEMS_CAPTURE_NO_MEMORY; > return NULL; > } > > @@ -301,13 +332,13 @@ rtems_capture_create_control (rtems_name name, rtems_id > id) > > memset (control->by, 0, sizeof (control->by)); > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > control->next = capture_controls; > capture_controls = control; > rtems_iterate_over_all_threads (rtems_capture_initialize_control); > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > } > > return control; > @@ -315,16 +346,18 @@ rtems_capture_create_control (rtems_name name, rtems_id > id) > > void rtems_capture_initialize_task( rtems_tcb* tcb ) > { > - rtems_capture_control_t* control; > - rtems_name name; > + rtems_capture_control_t* control; > + rtems_name name; > + rtems_interrupt_lock_context lock_context; > > /* > - * We need to scan the default control list to initialise > + * We need to scan the default control list to initialize > * this control if it is a new task. > */ > > rtems_object_get_classic_name( tcb->Object.id, &name ); > > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > if (tcb->Capture.control == NULL) { > for (control = capture_controls; control != NULL; control = > control->next) > if (rtems_capture_match_name_id (control->name, control->id, > @@ -333,28 +366,31 @@ void rtems_capture_initialize_task( rtems_tcb* tcb ) > } > > tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK; > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > } > > void rtems_capture_record_task( rtems_tcb* tcb ) > { > rtems_capture_task_record_t rec; > void* ptr; > + rtems_interrupt_lock_context lock_context; > > rtems_object_get_classic_name( tcb->Object.id, &rec.name ); > - > + > rec.stack_size = tcb->Start.Initial_stack.size; > rec.start_priority = _RTEMS_tasks_Priority_from_Core( > tcb->Start.initial_priority > ); > > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK; > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > /* > * Log the task information. The first time a task is > * seen a record is logged. This record can be identified > * by a 0 in the event identifier. > */ > - > rtems_capture_begin_add_record (tcb, 0, sizeof(rec), &ptr); > ptr = rtems_capture_append_to_record( > ptr, > @@ -375,14 +411,14 @@ void rtems_capture_record_task( rtems_tcb* tcb ) > } > > /* > - * This function indicates if data should be filtered from the > + * This function indicates if data should be filtered from the > * log. > */ > bool rtems_capture_filter( rtems_tcb* tcb, > uint32_t events) > { > if (tcb && > - ((capture_flags & > + ((capture_flags_global & > (RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) == > RTEMS_CAPTURE_TRIGGERED)) > { > @@ -398,7 +434,7 @@ bool rtems_capture_filter( rtems_tcb* tcb, > if ((events & RTEMS_CAPTURE_RECORD_EVENTS) || > ((tcb->real_priority >= capture_ceiling) && > (tcb->real_priority <= capture_floor) && > - ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) || > + ((capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH) || > (control && (control->flags & RTEMS_CAPTURE_WATCH))))) > { > return false; > @@ -420,7 +456,7 @@ rtems_capture_record_open (rtems_tcb* > tcb, > uint8_t* ptr; > rtems_capture_record_t* capture_in; > > - rtems_interrupt_lock_acquire (&capture_lock, lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_per_cpu, lock_context); > > ptr = rtems_capture_buffer_allocate(&capture_records, size); > capture_in = (rtems_capture_record_t *) ptr; > @@ -441,14 +477,14 @@ rtems_capture_record_open (rtems_tcb* > tcb, > ptr = ptr + sizeof(*capture_in); > } > else > - capture_flags |= RTEMS_CAPTURE_OVERFLOW; > + capture_flags_per_cpu |= RTEMS_CAPTURE_OVERFLOW; > > return ptr; > } > > void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* > lock_context) > { > - rtems_interrupt_lock_release (&capture_lock, lock_context); > + rtems_interrupt_lock_release (&capture_lock_per_cpu, lock_context); > } > > /* > @@ -460,11 +496,10 @@ rtems_capture_trigger (rtems_tcb* ft, > rtems_tcb* tt, > uint32_t events) > { > - > /* > * If we have not triggered then see if this is a trigger condition. > */ > - if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED)) > + if (!(capture_flags_global & RTEMS_CAPTURE_TRIGGERED)) > { > rtems_capture_control_t* fc = NULL; > rtems_capture_control_t* tc = NULL; > @@ -499,7 +534,7 @@ rtems_capture_trigger (rtems_tcb* ft, > */ > if (from_events || to_events) > { > - capture_flags |= RTEMS_CAPTURE_TRIGGERED; > + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED; > return 1; > } > > @@ -510,7 +545,7 @@ rtems_capture_trigger (rtems_tcb* ft, > { > if (rtems_capture_by_in_to (events, ft, tc)) > { > - capture_flags |= RTEMS_CAPTURE_TRIGGERED; > + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED; > return 1; > } > } > @@ -523,47 +558,61 @@ rtems_capture_trigger (rtems_tcb* ft, > > /* > * This function initialises the realtime capture engine allocating the trace > - * buffer. It is assumed we have a working heap at stage of initialisation. > + * buffer. It is assumed we have a working heap at stage of initialization. > */ > rtems_status_code > rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp > __attribute__((unused))) > { > - rtems_status_code sc; > + rtems_status_code sc = RTEMS_SUCCESSFUL; > + size_t count; > + uint32_t i; > + rtems_capture_buffer_t* buff; > > /* > * See if the capture engine is already open. > */ > > - if (capture_records.buffer) > + if ((capture_flags_global & RTEMS_CAPTURE_INIT) == RTEMS_CAPTURE_INIT) { > return RTEMS_RESOURCE_IN_USE; > + } > > - rtems_capture_buffer_create( &capture_records, size ); > + count = rtems_get_processor_count(); > + if (capture_per_cpu == NULL) { > + capture_per_cpu = calloc( count, sizeof(rtems_capture_per_cpu_data_t) ); > + } > > - if (capture_records.buffer == NULL) > - return RTEMS_NO_MEMORY; > + for (i=0; i<count; i++) { > + buff = &capture_records_on_cpu(i); > + rtems_capture_buffer_create( buff, size ); > + if (buff->buffer == NULL) { > + sc = RTEMS_NO_MEMORY; > + break; > + } > > - capture_count = 0; > - capture_flags = 0; > + capture_count_on_cpu(i) = 0; > + capture_flags_on_cpu(i) = 0; > + } > + > + capture_flags_global = 0; > capture_ceiling = 0; > capture_floor = 255; > - > - sc = rtems_capture_user_extension_open(); > + if (sc == RTEMS_SUCCESSFUL) > + sc = rtems_capture_user_extension_open(); > > if (sc != RTEMS_SUCCESSFUL) > { > - rtems_capture_buffer_destroy( &capture_records); > + for (i=0; i<count; i++) > + rtems_capture_buffer_destroy( &capture_records_on_cpu(i)); > + } else { > + capture_flags_global |= RTEMS_CAPTURE_INIT; > } > > - /* > - * Iterate over the list of existing tasks. > - */ > - > return sc; > } > > /* > * This function shutdowns the capture engine and release any claimed > - * resources. > + * resources. Capture control must be disabled prior to calling a close. > */ > rtems_status_code > rtems_capture_close (void) > @@ -571,18 +620,26 @@ rtems_capture_close (void) > rtems_interrupt_lock_context lock_context; > rtems_capture_control_t* control; > rtems_status_code sc; > + uint32_t cpu; > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > - if (!capture_records.buffer) > + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT) > { > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > return RTEMS_SUCCESSFUL; > } > > - capture_flags &= ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR); > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > + { > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > + return RTEMS_UNSATISFIED; > + } > + > + capture_flags_global &= > + ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR | RTEMS_CAPTURE_INIT); > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > /* > * Delete the extension first. This means we are now able to > @@ -600,16 +657,19 @@ rtems_capture_close (void) > { > rtems_capture_control_t* delete = control; > control = control->next; > - rtems_workspace_free (delete); > + free (delete); > } > > capture_controls = NULL; > - > - if (capture_records.buffer) > - { > - rtems_capture_buffer_destroy( &capture_records); > + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) { > + capture_count_on_cpu(cpu) = 0; > + if (capture_records_on_cpu(cpu).buffer) > + rtems_capture_buffer_destroy( &capture_records_on_cpu(cpu) ); > } > > + free( capture_per_cpu ); > + capture_per_cpu = NULL; > + > return RTEMS_SUCCESSFUL; > } > > @@ -618,20 +678,20 @@ rtems_capture_control (bool enable) > { > rtems_interrupt_lock_context lock_context; > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > - if (!capture_records.buffer) > + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT) > { > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > return RTEMS_UNSATISFIED; > } > > if (enable) > - capture_flags |= RTEMS_CAPTURE_ON; > + capture_flags_global |= RTEMS_CAPTURE_ON; > else > - capture_flags &= ~RTEMS_CAPTURE_ON; > + capture_flags_global &= ~RTEMS_CAPTURE_ON; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > return RTEMS_SUCCESSFUL; > } > @@ -646,20 +706,20 @@ rtems_capture_monitor (bool enable) > { > rtems_interrupt_lock_context lock_context; > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > - if (!capture_records.buffer) > + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT) > { > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > return RTEMS_UNSATISFIED; > } > > if (enable) > - capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR; > + capture_flags_global |= RTEMS_CAPTURE_ONLY_MONITOR; > else > - capture_flags &= ~RTEMS_CAPTURE_ONLY_MONITOR; > + capture_flags_global &= ~RTEMS_CAPTURE_ONLY_MONITOR; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > return RTEMS_SUCCESSFUL; > } > @@ -673,7 +733,6 @@ rtems_capture_flush_tcb (rtems_tcb *tcb) > tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED; > } > > - > /* > * This function flushes the capture buffer. The prime parameter allows the > * capture engine to also be primed again. > @@ -681,21 +740,36 @@ rtems_capture_flush_tcb (rtems_tcb *tcb) > rtems_status_code > rtems_capture_flush (bool prime) > { > - rtems_interrupt_lock_context lock_context; > + rtems_interrupt_lock_context lock_context_global; > + rtems_interrupt_lock_context lock_context_per_cpu; > + rtems_interrupt_lock* lock; > + uint32_t cpu; > + > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context_global); > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > + { > + rtems_interrupt_lock_release (&capture_lock_global, > &lock_context_global); > + return RTEMS_UNSATISFIED; > + } > > rtems_iterate_over_all_threads (rtems_capture_flush_tcb); > > if (prime) > - capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW); > + capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | > RTEMS_CAPTURE_OVERFLOW); > else > - capture_flags &= ~RTEMS_CAPTURE_OVERFLOW; > - > - rtems_capture_buffer_flush( &capture_records ); > - capture_count = 0; > + capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW; > + > + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) { > + lock = &(capture_lock_on_cpu( cpu )); > + rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu); > + capture_count_on_cpu(cpu) = 0; > + if (capture_records_on_cpu(cpu).buffer) > + rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) ); > + rtems_interrupt_lock_release (lock, &lock_context_per_cpu); > + } > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global); > > return RTEMS_SUCCESSFUL; > } > @@ -704,13 +778,16 @@ rtems_capture_flush (bool prime) > * This function defines a watch for a specific task given a name. A watch > * causes it to be traced either in or out of context. The watch can be > * optionally enabled or disabled with the set routine. It is disabled by > - * default. > + * default. A watch can only be defined when capture control is disabled > */ > rtems_status_code > rtems_capture_watch_add (rtems_name name, rtems_id id) > { > rtems_capture_control_t* control; > > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > + return RTEMS_UNSATISFIED; > + > if ((name == 0) && (id == 0)) > return RTEMS_UNSATISFIED; > > @@ -731,7 +808,8 @@ rtems_capture_watch_add (rtems_name name, rtems_id id) > /* > * This function removes a watch for a specific task given a name. The task > * description will still exist if referenced by a trace record in the trace > - * buffer or a global watch is defined. > + * buffer or a global watch is defined. A watch can only be deleted when > + * capture control is disabled. > */ > rtems_status_code > rtems_capture_watch_del (rtems_name name, rtems_id id) > @@ -741,6 +819,9 @@ rtems_capture_watch_del (rtems_name name, rtems_id id) > rtems_capture_control_t** prev_control; > bool found = false; > > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > + return RTEMS_UNSATISFIED; > + > /* > * Should this test be for wildcards ? > */ > @@ -750,13 +831,13 @@ rtems_capture_watch_del (rtems_name name, rtems_id id) > { > if (rtems_capture_match_name_id (control->name, control->id, name, id)) > { > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > *prev_control = control->next; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > - rtems_workspace_free (control); > + free (control); > > control = *prev_control; > > @@ -786,6 +867,9 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, > bool enable) > rtems_capture_control_t* control; > bool found = false; > > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > + return RTEMS_UNSATISFIED; > + > /* > * Find the control and then set the watch. It must exist before it can > * be controlled. > @@ -794,14 +878,14 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, > bool enable) > { > if (rtems_capture_match_name_id (control->name, control->id, name, id)) > { > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > if (enable) > control->flags |= RTEMS_CAPTURE_WATCH; > else > control->flags &= ~RTEMS_CAPTURE_WATCH; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > found = true; > } > @@ -823,18 +907,18 @@ rtems_capture_watch_global (bool enable) > { > rtems_interrupt_lock_context lock_context; > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context); > > /* > * We need to keep specific and global watches separate so > * a global enable/disable does not lose a specific watch. > */ > if (enable) > - capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH; > + capture_flags_global |= RTEMS_CAPTURE_GLOBAL_WATCH; > else > - capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH; > + capture_flags_global &= ~RTEMS_CAPTURE_GLOBAL_WATCH; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (&capture_lock_global, &lock_context); > > return RTEMS_SUCCESSFUL; > } > @@ -845,7 +929,7 @@ rtems_capture_watch_global (bool enable) > bool > rtems_capture_watch_global_on (void) > { > - return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0; > + return capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0; > } > > /* > @@ -1082,30 +1166,26 @@ rtems_capture_clear_trigger (rtems_name > from_name, > } > > static inline uint32_t rtems_capture_count_records( void* recs, size_t size ) > -{ > +{ > rtems_capture_record_t* rec; > uint8_t* ptr = recs; > uint32_t rec_count = 0; > size_t byte_count = 0; > - > - > + > + > while (byte_count < size) { > rec = (rtems_capture_record_t*) ptr; > rec_count++; > _Assert( rec->size >= sizeof(*rec) ); > ptr += rec->size; > byte_count += rec->size; > - _Assert( rec_count <= capture_count ); > }; > - > + > return rec_count; > } > > /* > * This function reads a number of records from the capture buffer. > - * The user can optionally block and wait until the buffer as a > - * specific number of records available or a specific time has > - * elasped. > * > * The function returns the number of record that is has that are > * in a continous block of memory. If the number of available records > @@ -1117,106 +1197,47 @@ static inline uint32_t rtems_capture_count_records( > void* recs, size_t size ) > * The user must release the records. This is achieved with a call to > * rtems_capture_release. Calls this function without a release will > * result in at least the same number of records being released. > - * > - * The 'threshold' parameter is the number of records that must be > - * captured before returning. If a timeout period is specified (non-0) > - * any captured records will be returned. These parameters stop > - * thrashing occuring for a small number of records, yet allows > - * a user configured latiency to be applied for single events. > - * > - * The 'timeout' parameter is in micro-seconds. A value of 0 will disable > - * the timeout. > */ > rtems_status_code > -rtems_capture_read (uint32_t threshold, > - uint32_t timeout, > +rtems_capture_read (uint32_t cpu, > uint32_t* read, > rtems_capture_record_t** recs) > { > rtems_interrupt_lock_context lock_context; > rtems_status_code sc = RTEMS_SUCCESSFUL; > size_t recs_size = 0; > - bool wrapped; > + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu )); > + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu )); > + uint32_t* flags = &(capture_flags_on_cpu( cpu )); > > *read = 0; > *recs = NULL; > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (lock, &lock_context); > > /* > * Only one reader is allowed. > */ > > - if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE) > + if (*flags & RTEMS_CAPTURE_READER_ACTIVE) > { > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (lock, &lock_context); > return RTEMS_RESOURCE_IN_USE; > } > > - capture_flags |= RTEMS_CAPTURE_READER_ACTIVE; > - > - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size ); > - *read = rtems_capture_count_records( *recs, recs_size ); > - > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > - > - for (;;) > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) > { > - /* > - * See if the data wraps the end of the record buffer. > - */ > - wrapped = rtems_capture_buffer_has_wrapped( &capture_records); > - > - /* > - * Do we have a threshold and have not wrapped > - * around the end of the capture record buffer ? > - */ > - if ((!wrapped) && threshold) > - { > - /* > - * Do we have enough records ? > - */ > - if (*read < threshold) > - { > - rtems_event_set event_out; > - > - rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader); > - > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > - > - capture_flags |= RTEMS_CAPTURE_READER_WAITING; > - > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > - > - sc = rtems_event_receive (RTEMS_EVENT_0, > - RTEMS_WAIT | RTEMS_EVENT_ANY, > - RTEMS_MICROSECONDS_TO_TICKS (timeout), > - &event_out); > - > - /* > - * Let the user handle all other sorts of errors. This may > - * not be the best solution, but oh well, it will do for > - * now. > - */ > - if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT)) > - break; > - > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (lock, &lock_context); > + return RTEMS_UNSATISFIED; > + } > > - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size ); > - *read = rtems_capture_count_records( *recs, recs_size ); > + *flags |= RTEMS_CAPTURE_READER_ACTIVE; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + *recs = rtems_capture_buffer_peek( records, &recs_size ); > > - continue; > - } > - } > + *read = rtems_capture_count_records( *recs, recs_size ); > > - /* > - * Always out if we reach here. To loop use continue. > - */ > - break; > - } > + rtems_interrupt_lock_release (lock, &lock_context); > > return sc; > } > @@ -1226,7 +1247,7 @@ rtems_capture_read (uint32_t threshold, > * to the capture engine. The count must match the number read. > */ > rtems_status_code > -rtems_capture_release (uint32_t count) > +rtems_capture_release (uint32_t cpu, uint32_t count) > { > rtems_interrupt_lock_context lock_context; > uint8_t* ptr; > @@ -1235,43 +1256,49 @@ rtems_capture_release (uint32_t count) > size_t ptr_size = 0; > size_t rel_size = 0; > rtems_status_code ret_val = RTEMS_SUCCESSFUL; > + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu )); > + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu )); > + uint32_t* flags = &(capture_flags_on_cpu( cpu )); > + uint32_t* total = &(capture_count_on_cpu( cpu )); > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > + rtems_interrupt_lock_acquire (lock, &lock_context); > > - if (count > capture_count) > - count = capture_count; > + if (count > *total) { > + count = *total; > + } > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) { > + rtems_interrupt_lock_release (lock, &lock_context); > + return RTEMS_UNSATISFIED; > + } > > counted = count; > - > - ptr = rtems_capture_buffer_peek( &capture_records, &ptr_size ); > + > + ptr = rtems_capture_buffer_peek( records, &ptr_size ); > _Assert(ptr_size >= (count * sizeof(*rec) )); > > rel_size = 0; > - while (counted--) > - { > + while (counted--) { > rec = (rtems_capture_record_t*) ptr; > rel_size += rec->size; > _Assert( rel_size <= ptr_size ); > ptr += rec->size; > } > > - rtems_interrupt_lock_acquire (&capture_lock, &lock_context); > - > if (rel_size > ptr_size ) { > ret_val = RTEMS_INVALID_NUMBER; > rel_size = ptr_size; > } > > - capture_count -= count; > + *total -= count; > > - if (count) > - rtems_capture_buffer_free( &capture_records, rel_size ); > + if (count) { > + rtems_capture_buffer_free( records, rel_size ); > + } > > - capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE; > + *flags &= ~RTEMS_CAPTURE_READER_ACTIVE; > > - rtems_interrupt_lock_release (&capture_lock, &lock_context); > + rtems_interrupt_lock_release (lock, &lock_context); > > return ret_val; > } > @@ -1308,5 +1335,3 @@ rtems_capture_get_control_list (void) > { > return capture_controls; > } > - > - > diff --git a/cpukit/libmisc/capture/capture.h > b/cpukit/libmisc/capture/capture.h > index f907686..63d1343 100644 > --- a/cpukit/libmisc/capture/capture.h > +++ b/cpukit/libmisc/capture/capture.h > @@ -15,7 +15,7 @@ > All rights reserved Objective Design Systems Pty Ltd, 2002 > Chris Johns (c...@acm.org) > > - COPYRIGHT (c) 1989-1998. > + COPYRIGHT (c) 1989-2014 > On-Line Applications Research Corporation (OAR). > > The license and distribution terms for this file may be > @@ -245,8 +245,8 @@ typedef void > (*rtems_capture_timestamp)(rtems_capture_time_t* time); > * initialisation. > * > * @param[in] size The number of capture records to define. > - * @param[in] timestamp The timestamp callout handler to use. If the > - * the handler is NULL a default nano-second timestamp > + * @param[in] timestamp The timestamp callout handler to use. If the > + * the handler is NULL a default nano-second timestamp > * will be used. > * > * @retval This method returns RTEMS_SUCCESSFUL if there was not an > @@ -390,7 +390,7 @@ rtems_capture_watch_global (bool enable); > * > * This function returns the global watch state. > * > - * @retval This method returns true if the global watch > + * @retval This method returns true if the global watch > * is on. Otherwise, it returns false. > */ > bool > @@ -419,7 +419,7 @@ rtems_capture_watch_ceiling (rtems_task_priority ceiling); > * > * This function gets the watch ceiling. > * > - * @retval The priority level immediately above that at which events > + * @retval The priority level immediately above that at which events > * from tasks are not captured. > */ > rtems_task_priority > @@ -520,9 +520,6 @@ rtems_capture_clear_trigger (rtems_name > from_name, > * @brief Capture read records from capture buffer > * > * This function reads a number of records from the capture buffer. > - * The user can optionally block and wait until the buffer as a > - * specific number of records available or a specific time has > - * elasped. > * > * The function returns the number of record that is has that are > * in a continous block of memory. If the number of available records > @@ -535,17 +532,7 @@ rtems_capture_clear_trigger (rtems_name > from_name, > * rtems_capture_release. Calls this function without a release will > * result in at least the same number of records being released. > * > - * The 'threshold' parameter is the number of records that must be > - * captured before returning. If a timeout period is specified (non-0) > - * any captured records will be returned. These parameters stop > - * thrashing occuring for a small number of records, yet allows > - * a user configured latiency to be applied for single events. > - * > - * The @a timeout parameter is in microseconds. A value of 0 will > - * disable the timeout. > - * > - * @param[in] threshold The number of records that must be captured > - * @param[in] timeout The micro-second timeout period > + * @param[in] cpu The cpu number that the records were recorded on > * @param[out] read will contain the number of records read > * @param[out] recs The capture records that are read. > * > @@ -554,8 +541,7 @@ rtems_capture_clear_trigger (rtems_name > from_name, > * source of the error. > */ > rtems_status_code > -rtems_capture_read (uint32_t threshold, > - uint32_t timeout, > +rtems_capture_read (uint32_t cpu, > uint32_t* read, > rtems_capture_record_t** recs); > > @@ -566,13 +552,13 @@ rtems_capture_read (uint32_t threshold, > * to the capture engine. The count must match the number read. > * > * @param[in] count The number of record slots to release > - * > + * > * @retval This method returns RTEMS_SUCCESSFUL if there was not an > * error. Otherwise, a status code is returned indicating the > * source of the error. > */ > rtems_status_code > -rtems_capture_release (uint32_t count); > +rtems_capture_release (uint32_t cpu, uint32_t count); > > /* > * @brief Capture nano-second time period. > @@ -609,7 +595,7 @@ void rtems_capture_initialize_task( rtems_tcb* tcb ); > > /** > * @brief Capture record task. > - * > + * > * This function records a new capture task record. > * > * @param[in] tcb is the task control block for the task > @@ -631,7 +617,7 @@ static inline bool rtems_capture_task_recorded( > rtems_tcb* tcb ) { > /** > * @brief Capture task initialized > * > - * This function returns true if this task information has been > + * This function returns true if this task information has been > * initialized. > * > * @param[in] tcb is the task control block for the task > @@ -642,11 +628,11 @@ static inline bool rtems_capture_task_initialized( > rtems_tcb* tcb ) { > > /** > * @brief Capture get task id. > - * > + * > * This function returns the task id. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task id. > */ > static inline rtems_id > @@ -657,11 +643,11 @@ rtems_capture_task_id (rtems_tcb* tcb) > > /** > * @brief Capture get task state. > - * > + * > * This function returns the task state. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task state. > */ > static inline States_Control > @@ -674,11 +660,11 @@ rtems_capture_task_state (rtems_tcb* tcb) > > /** > * @brief Capture get task name. > - * > + * > * This function returns the task name. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task name. > */ > static inline rtems_name > @@ -691,11 +677,11 @@ rtems_capture_task_name (rtems_tcb* tcb) > > /** > * @brief Capture get task flags. > - * > + * > * This function returns the task flags. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task flags. > */ > static inline uint32_t > @@ -706,11 +692,11 @@ rtems_capture_task_flags (rtems_tcb* tcb) > > /** > * @brief Capture get task control > - * > + * > * This function returns the task control if present. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task control if present. > */ > static inline rtems_capture_control_t* > @@ -721,11 +707,11 @@ rtems_capture_task_control (rtems_tcb* tcb) > > /** > * @brief Capture get task control flags. > - * > + * > * This function returns the task control flags if a control is present. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the task control flags if a control is > present. > */ > static inline uint32_t > @@ -739,12 +725,12 @@ rtems_capture_task_control_flags (rtems_tcb* tcb) > > /** > * @brief Capture get task start priority. > - * > + * > * This function returns the tasks start priority. The tracer needs this > * to track where the task's priority goes. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the tasks start priority. The tracer needs > this > * to track where the task's priority goes. > */ > @@ -758,11 +744,11 @@ rtems_capture_task_start_priority (rtems_tcb* tcb) > > /** > * @brief Capture get task real priority. > - * > + * > * This function returns the tasks real priority. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the tasks real priority. > */ > static inline rtems_task_priority > @@ -773,11 +759,11 @@ rtems_capture_task_real_priority (rtems_tcb* tcb) > > /** > * @brief Capture get task current priority. > - * > + * > * This function returns the tasks current priority. > * > * @param[in] task The capture task. > - * > + * > * @retval This function returns the tasks current priority. > */ > static inline rtems_task_priority > @@ -800,12 +786,12 @@ rtems_capture_get_control_list (void); > > /** > * @brief Capture get next capture control. > - * > + * > * This function returns the pointer to the next control in the list. The > * pointer NULL terminates the list. > * > * @param[in] control the current capture control. > - * > + * > * @retval This function returns the pointer to the next control in the > list. The > * pointer NULL terminates the list. > */ > @@ -817,11 +803,11 @@ rtems_capture_next_control (rtems_capture_control_t* > control) > > /** > * @brief Capture get capture control id. > - * > + * > * This function returns the control id. > * > * @param[in] control the capture control. > - * > + * > * @retval This function returns the control id. > */ > static inline rtems_id > @@ -943,7 +929,7 @@ rtems_capture_control_by_name (rtems_capture_control_t* > control, int by) > * @brief Capture get capture control by task id. > * > * This function returns the control @a by task id > - * > + * > * @retval This function returns the control @a by task id. > */ > static inline rtems_id > diff --git a/cpukit/libmisc/capture/capture_buffer.c > b/cpukit/libmisc/capture/capture_buffer.c > index 9557f70..6f557a9 100644 > --- a/cpukit/libmisc/capture/capture_buffer.c > +++ b/cpukit/libmisc/capture/capture_buffer.c > @@ -84,10 +84,10 @@ void * rtems_capture_buffer_allocate( > rtems_capture_buffer_t* buffer, size_t siz > buffer->head = size; > buffer->count = buffer->count + size; > > - return ptr; > + return ptr; > } > > -void *rtems_capture_buffer_free( rtems_capture_buffer_t* buffer, size_t size > ) > +void *rtems_capture_buffer_free( rtems_capture_buffer_t* buffer, size_t size > ) > { > static void *ptr; > static uint32_t next; > @@ -112,6 +112,6 @@ void *rtems_capture_buffer_free( rtems_capture_buffer_t* > buffer, size_t size ) > } else { > buffer->tail = next; > } > - > + > return ptr; > } > diff --git a/cpukit/libmisc/capture/capture_buffer.h > b/cpukit/libmisc/capture/capture_buffer.h > index a01ca29..ebcc464 100644 > --- a/cpukit/libmisc/capture/capture_buffer.h > +++ b/cpukit/libmisc/capture/capture_buffer.h > @@ -79,14 +79,14 @@ static inline bool rtems_capture_buffer_has_wrapped( > rtems_capture_buffer_t* buf > return false; > } > > -static inline void *rtems_capture_buffer_peek( rtems_capture_buffer_t* > buffer, size_t *size ) > +static inline void *rtems_capture_buffer_peek( rtems_capture_buffer_t* > buffer, size_t *size ) > { > if (rtems_capture_buffer_is_empty(buffer)) { > - *size = 0; > + *size = 0; > return NULL; > } > > - if ( buffer->tail > buffer->head) > + if ( buffer->tail > buffer->head) > *size = buffer->end - buffer->tail; > else > *size = buffer->head - buffer->tail; > diff --git a/cpukit/libmisc/capture/capture_support.c > b/cpukit/libmisc/capture/capture_support.c > new file mode 100644 > index 0000000..bdfd37b > --- /dev/null > +++ b/cpukit/libmisc/capture/capture_support.c > @@ -0,0 +1,307 @@ > +/* > + ------------------------------------------------------------------------ > + > + Copyright Objective Design Systems Pty Ltd, 2002 > + All rights reserved Objective Design Systems Pty Ltd, 2002 > + Chris Johns (c...@acm.org) > + > + COPYRIGHT (c) 1989-2014. > + On-Line Applications Research Corporation (OAR). > + > + The license and distribution terms for this file may be > + found in the file LICENSE in this distribution. > + > + This software with is provided ``as is'' and with NO WARRANTY. > + > + ------------------------------------------------------------------------ > + > + RTEMS Performance Monitoring and Measurement Framework. > + > + This is a set of print support routines that may be shared between > + the RTEMS monitor and direct callers of the capture engine. > + > +*/ > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#include <ctype.h> > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <inttypes.h> > + > +#include <rtems.h> > +#include <rtems/monitor.h> > +#include <rtems/captureimpl.h> > + > +/* > + * Structure used during printing of the capture records. > + */ > + > +typedef struct { > + rtems_capture_record_t* rec; > + uint32_t read; > + uint32_t last_t; > + uint32_t printed; > +} ctrace_per_cpu_t; > + > +/* > + * rtems_catpure_print_uptime > + * > + * DESCRIPTION: > + * > + * This function prints the nanosecond uptime to stdout. > + */ > +void > +rtems_capture_print_timestamp (uint64_t uptime) > +{ > + uint32_t hours; > + uint32_t minutes; > + uint32_t seconds; > + uint32_t nanosecs; > + > + seconds = uptime / 1000000000LLU; > + minutes = seconds / 60; > + hours = minutes / 60; > + minutes = minutes % 60; > + seconds = seconds % 60; > + nanosecs = uptime % 1000000000; > + > + fprintf (stdout, "%5lu:%02lu:%02lu.%09lu", hours, minutes, seconds, > nanosecs); > +} > + > +void > +rtems_capture_print_record_task( uint32_t cpu, rtems_capture_record_t* rec) > +{ > + rtems_capture_task_record_t* task_rec = (rtems_capture_task_record_t*) rec; > + > + fprintf(stdout,"%2" PRId32 " ", cpu); > + rtems_capture_print_timestamp (rec->time); > + fprintf (stdout, " "); > + rtems_monitor_dump_id (rec->task_id); > + fprintf (stdout, " %c%c%c%c", > + (char) (task_rec->name >> 24) & 0xff, > + (char) (task_rec->name >> 16) & 0xff, > + (char) (task_rec->name >> 8) & 0xff, > + (char) (task_rec->name >> 0) & 0xff); > + fprintf(stdout, " %3" PRId32 " %3" PRId32 " ", > + (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, > + (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff ); > + fprintf (stdout, "%3" PRId32 " %3" PRId32 " TASK_RECORD\n", > + task_rec->start_priority, > + task_rec->stack_size); > +} > + > +void > +rtems_capture_print_record_capture( > + uint32_t cpu, > + rtems_capture_record_t* rec, > + uint64_t diff > +){ > + uint32_t event; > + int e; > + > + event = rec->events >> RTEMS_CAPTURE_EVENT_START; > + for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++) > + { > + if (event & 1) > + { > + fprintf(stdout,"%2" PRId32 " ", cpu); > + rtems_capture_print_timestamp (rec->time); > + fprintf (stdout, " %10" PRId64 " ", diff); > + rtems_monitor_dump_id (rec->task_id); > + fprintf(stdout, " %3" PRId32 " %3" PRId32 " %s\n", > + (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, > + (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, > + rtems_capture_event_text (e)); > + } > + event >>= 1; > + } > +} > + > +/* > + * rtems_capture_print_trace_records > + * > + * DESCRIPTION: > + * > + * This function is a monitor command that dumps trace records. > + * > + */ > + > +void > +rtems_capture_print_trace_records ( int total, bool csv ) > +{ > + rtems_status_code sc; > + int count; > + ctrace_per_cpu_t* per_cpu; > + uint8_t* ptr; > + uint32_t i; > + uint32_t cpu = 0; > + rtems_capture_record_t* rec_out; > + > + count = rtems_get_processor_count(); > + per_cpu = calloc( count, sizeof(*per_cpu) ); > + > + while (total) > + { > + /* Prime the per_cpu data */ > + for (i=0; i< count; i++) { > + if ( per_cpu[i].read == 0 ) { > + sc = rtems_capture_read (i, &per_cpu[i].read, &per_cpu[i].rec); > + if (sc != RTEMS_SUCCESSFUL) > + { > + fprintf (stdout, "error: trace read failed: %s\n", > rtems_status_text (sc)); > + rtems_capture_flush (0); > + return; > + } > + /* Release the buffer if there are no records to read */ > + if (per_cpu[i].read == 0) > + rtems_capture_release (i, 0); > + } > + } > + > + /* Find the next record to print */ > + rec_out = NULL; > + for (i=0; i< count; i++) { > + > + if ((rec_out == NULL) || > + ((per_cpu[i].read != 0) && (rec_out->time > > per_cpu[i].rec->time))) { > + rec_out = per_cpu[i].rec; > + cpu = i; > + } > + } > + > + /* If we have read all the records abort. */ > + if (rec_out == NULL) > + break; > + > + /* Print the record */ > + if (csv) > + fprintf (stdout, "%03" PRIu32 ",%08" PRIu32 ",%03" PRIu32 > + ",%03" PRIu32 ",%04" PRIx32 ",%" PRId64 "\n", > + cpu, rec_out->task_id, > + (rec_out->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & > 0xff, > + (rec_out->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & > 0xff, > + (rec_out->events >> RTEMS_CAPTURE_EVENT_START), > + (uint64_t) rec_out->time); > + else { > + if ((rec_out->events >> RTEMS_CAPTURE_EVENT_START) == 0) > + rtems_capture_print_record_task(cpu, rec_out ); > + else { > + uint64_t diff = 0; > + if (per_cpu[cpu].last_t) > + diff = rec_out->time - per_cpu[cpu].last_t; > + per_cpu[cpu].last_t = rec_out->time; > + > + rtems_capture_print_record_capture( cpu, rec_out, diff ); > + } > + } > + > + /* > + * If we have not printed all the records read > + * increment to the next record. If we have > + * printed all records release the records printed. > + */ > + per_cpu[cpu].printed++; > + if (per_cpu[cpu].printed != per_cpu[cpu].read) { > + ptr = (uint8_t *)per_cpu[cpu].rec; > + ptr += per_cpu[cpu].rec->size; > + per_cpu[cpu].rec = (rtems_capture_record_t *)ptr; > + } else { > + rtems_capture_release (cpu, per_cpu[cpu].printed); > + per_cpu[cpu].read = 0; > + per_cpu[cpu].printed = 0; > + } > + > + total --; > + } > + > + /* Finished so release all the records that were printed. */ > + for (i=0; i< count; i++) { > + if ( per_cpu[i].read != 0 ) { > + rtems_capture_release( i, per_cpu[i].printed ); > + } > + } > + > + free( per_cpu ); > +} > + > +void > +rtems_capture_print_watch_list () > +{ > + rtems_capture_control_t* control = rtems_capture_get_control_list (); > + rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); > + rtems_task_priority floor = rtems_capture_watch_get_floor (); > + > + fprintf (stdout, "watch priority ceiling is %" PRId32 "\n", ceiling); > + fprintf (stdout, "watch priority floor is %" PRId32 "\n", floor); > + fprintf (stdout, "global watch is %s\n", > + rtems_capture_watch_global_on () ? "enabled" : "disabled"); > + fprintf (stdout, "total %" PRId32 "\n", rtems_capture_control_count ()); > + > + while (control) > + { > + uint32_t flags; > + int f; > + int fshowed; > + int lf; > + > + fprintf (stdout, " "); > + rtems_monitor_dump_id (rtems_capture_control_id (control)); > + fprintf (stdout, " "); > + rtems_monitor_dump_name (rtems_capture_control_name (control)); > + flags = rtems_capture_control_flags (control); > + fprintf (stdout, " %c%c ", > + rtems_capture_watch_global_on () ? 'g' : '-', > + flags & RTEMS_CAPTURE_WATCH ? 'w' : '-'); > + flags = rtems_capture_control_to_triggers (control); > + fprintf (stdout, " T:%c%c%c%c%c%c%c", > + flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > + flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > + flags & RTEMS_CAPTURE_START ? 'S' : '-', > + flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > + flags & RTEMS_CAPTURE_DELETE ? 'D' : '-', > + flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-', > + flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-'); > + flags = rtems_capture_control_from_triggers (control); > + fprintf (stdout, " F:%c%c%c%c%c", > + flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > + flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > + flags & RTEMS_CAPTURE_START ? 'S' : '-', > + flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > + flags & RTEMS_CAPTURE_DELETE ? 'D' : '-'); > + > + for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++) > + { > + if (rtems_capture_control_by_valid (control, f)) > + { > + if (lf && ((fshowed % 3) == 0)) > + { > + fprintf (stdout, "\n"); > + lf = 0; > + } > + > + fprintf (stdout, " %2i:", f); > + rtems_monitor_dump_name (rtems_capture_control_by_name (control, f)); > + fprintf (stdout, "/"); > + rtems_monitor_dump_id (rtems_capture_control_by_id (control, f)); > + flags = rtems_capture_control_by_triggers (control, f); > + fprintf (stdout, ":%c%c%c%c%c", > + flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-', > + flags & RTEMS_CAPTURE_CREATE ? 'C' : '-', > + flags & RTEMS_CAPTURE_START ? 'S' : '-', > + flags & RTEMS_CAPTURE_RESTART ? 'R' : '-', > + flags & RTEMS_CAPTURE_DELETE ? 'D' : '-'); > + fshowed++; > + lf = 1; > + } > + } > + > + if (lf) > + fprintf (stdout, "\n"); > + > + control = rtems_capture_next_control (control); > + } > +} > diff --git a/cpukit/libmisc/capture/capture_user_extension.c > b/cpukit/libmisc/capture/capture_user_extension.c > index 69b8d48..37372cb 100644 > --- a/cpukit/libmisc/capture/capture_user_extension.c > +++ b/cpukit/libmisc/capture/capture_user_extension.c > @@ -5,7 +5,7 @@ > All rights reserved Objective Design Systems Pty Ltd, 2002 > Chris Johns (c...@acm.org) > > - COPYRIGHT (c) 1989-2009. > + COPYRIGHT (c) 1989-2014. > On-Line Applications Research Corporation (OAR). > > The license and distribution terms for this file may be > @@ -18,10 +18,6 @@ > RTEMS Performance Monitoring and Measurement Framework. > > This is the Capture Engine component. > -rtems_status_code rtems_capture_user_extension_open(void); > -rtems_status_code rtems_capture_user_extension_close(void); > - > - > */ > > #ifdef HAVE_CONFIG_H > @@ -43,8 +39,8 @@ rtems_status_code rtems_capture_user_extension_close(void); > */ > static rtems_id capture_id; > > -static bool > -rtems_capture_create_task (rtems_tcb* current_task, > +static bool > +rtems_capture_create_task (rtems_tcb* current_task, > rtems_tcb* new_task); > > static void > @@ -95,7 +91,7 @@ static inline void rtems_capture_record ( > > if (rtems_capture_filter( tcb, events) ) > return; > - > + > if (!rtems_capture_task_recorded (tcb)) > rtems_capture_record_task (tcb); > > @@ -143,7 +139,6 @@ rtems_capture_create_task (rtems_tcb* ct, > * The task pointers may not be known as the task may have > * been created before the capture engine was open. Add them. > */ > - > if (!rtems_capture_task_initialized (ct)) > rtems_capture_initialize_task (ct); > > @@ -176,7 +171,7 @@ rtems_capture_start_task (rtems_tcb* ct, > if (!rtems_capture_task_initialized (ct)) > rtems_capture_initialize_task (ct); > > - if (st == NULL) > + if (st != NULL) > rtems_capture_initialize_task (st); > > if (rtems_capture_trigger (ct, st, RTEMS_CAPTURE_START)) > @@ -197,7 +192,6 @@ rtems_capture_restart_task (rtems_tcb* ct, > * The task pointers may not be known as the task may have > * been created before the capture engine was open. Add them. > */ > - > if (!rtems_capture_task_initialized (ct)) > rtems_capture_initialize_task (ct); > > @@ -302,7 +296,6 @@ rtems_capture_switch_task (rtems_tcb* ct, > if (flags & RTEMS_CAPTURE_ON) > { > rtems_capture_time_t time; > - > if (!rtems_capture_task_initialized (ct)) > rtems_capture_initialize_task (ct); > > diff --git a/cpukit/libmisc/capture/captureimpl.h > b/cpukit/libmisc/capture/captureimpl.h > index 3c2f6c3..77a6f07 100644 > --- a/cpukit/libmisc/capture/captureimpl.h > +++ b/cpukit/libmisc/capture/captureimpl.h > @@ -1,7 +1,7 @@ > /** > * @file rtems/captureimpl.h > * > - * @brief Capture Implementation file > + * @brief Capture Implementation file > * > * This file contains an interface between the capture engine and > * capture user extension methods. > @@ -43,20 +43,25 @@ extern "C" { > /* > * Global capture flags. > */ > -#define RTEMS_CAPTURE_ON (1U << 0) > -#define RTEMS_CAPTURE_NO_MEMORY (1U << 1) > -#define RTEMS_CAPTURE_OVERFLOW (1U << 2) > +#define RTEMS_CAPTURE_INIT (1u << 0) > +#define RTEMS_CAPTURE_ON (1U << 1) > +#define RTEMS_CAPTURE_NO_MEMORY (1U << 2) > #define RTEMS_CAPTURE_TRIGGERED (1U << 3) > -#define RTEMS_CAPTURE_READER_ACTIVE (1U << 4) > -#define RTEMS_CAPTURE_READER_WAITING (1U << 5) > -#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 6) > -#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 7) > +#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 4) > +#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 5) > + > +/* > + * Per-CPU capture flags. > + */ > +#define RTEMS_CAPTURE_OVERFLOW (1U << 0) > +#define RTEMS_CAPTURE_READER_ACTIVE (1U << 1) > +#define RTEMS_CAPTURE_READER_WAITING (1U << 2) > > /** > * @brief Capture set extension index. > * > * This function is used to set the extension index > - * for the capture engine. > + * for the capture engine. > * > * @param[in] index specifies the extension index to be > * used for capture engine data. > @@ -81,7 +86,7 @@ int rtems_capture_get_extension_index(void); > * > * @retval This method returns the global capture > * flags. > - * > + * > */ > uint32_t rtems_capture_get_flags(void); > > @@ -133,7 +138,7 @@ bool rtems_capture_trigger (rtems_tcb* ft, > uint32_t events); > > /** > - * @brief Capture append to record > + * @brief Capture append to record > * > * This function Capture appends data to a capture record. It should > * be called between rtems_capture_begin_add_record and > @@ -145,10 +150,10 @@ bool rtems_capture_trigger (rtems_tcb* ft, > * > * @retval This method returns a pointer which is used as a marker > * for the next location in the capture record. it should only be > - * used as input into rtems_capture_append_to_record or > + * used as input into rtems_capture_append_to_record or > * rtems_capture_end_add_record. > */ > -static void *rtems_capture_append_to_record(void* rec, > +static void *rtems_capture_append_to_record(void* rec, > void* data, > size_t size ); > > @@ -162,7 +167,7 @@ static void *rtems_capture_append_to_record(void* rec, > * @param[in] events specifies the events > * > * @retval This method returns true if this data should be > - * filtered from the log. It returns false if this data > + * filtered from the log. It returns false if this data > * should be logged. > */ > bool rtems_capture_filter( rtems_tcb* task, > @@ -188,13 +193,13 @@ bool rtems_capture_filter( rtems_tcb* task, > * > * This function appends data of a specifed size into a capture record. > * > - * @param[in] rec specifies the next write point in the capture record > + * @param[in] rec specifies the next write point in the capture record > * @param[in] data specifies the data to write > * @param[in] size specifies the size of the data > * > * @retval This method returns the next write point in the capture record. > */ > -static inline void *rtems_capture_append_to_record(void* rec, > +static inline void *rtems_capture_append_to_record(void* rec, > void* data, > size_t size ) > { > @@ -230,9 +235,9 @@ void rtems_capture_get_time (rtems_capture_time_t* time); > /** > * @brief Capture record open. > * > - * This function allocates a record and fills in the > + * This function allocates a record and fills in the > * header information. It does a lock acquire > - * which will remain in effect until > + * which will remain in effect until > * rtems_capture_record_close is called. This method > * should only be used by rtems_capture_begin_add_record. > * > @@ -251,7 +256,7 @@ void* rtems_capture_record_open (rtems_tcb* > task, > /** > * @brief Capture record close. > * > - * This function closes writing to capure record and > + * This function closes writing to capure record and > * releases the lock that was held on the record. This > * method should only be used by rtems_capture_end_add_record. > * > @@ -261,6 +266,65 @@ void* rtems_capture_record_open (rtems_tcb* > task, > void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* > lock_context); > > > +/** > + * @brief Capture print trace records. > + * > + * This function reads, prints and releases up to > + * total trace records in either a csv format or an > + * ascii table format. > + * > + * @param[in] total specifies the number of records to print > + * @param[in] csv specifies a comma seperated value format > + */ > +void rtems_capture_print_trace_records ( int total, bool csv ); > + > +/** > + * @brief Capture print timestamp. > + * > + * This function prints uptime in a timestamp format. > + * > + * @param[in] uptime specifies the timestamp to print > + */ > +void rtems_capture_print_timestamp (uint64_t uptime); > + > +/** > + * @brief Capture print record task. > + * > + * This function prints a capture record task. This > + * record contains information to identify a task. It > + * is refrenced in other records by the task id. > + * > + * @param[in] cpu specifies the cpu the cpu the record was logged on. > + * @param[in] rec specifies the task record. > + */ > +void rtems_capture_print_record_task( > + uint32_t cpu, > + rtems_capture_record_t* rec > +); > + > +/** > + * @brief Capture print capture record. > + * > + * This function prints a user extension > + * capture record. > + * > + * @param[in] cpu specifies the cpu the cpu the record was logged on. > + * @param[in] rec specifies the record. > + * @param[in] diff specifies the time between this and the last capture > record. > + */ > +void rtems_capture_print_record_capture( > + uint32_t cpu, > + rtems_capture_record_t* rec, > + uint64_t diff > +); > + > +/** > + * @brief Capture print watch list > + * > + * This function prints a capture watch list > + */ > +void rtems_capture_print_watch_list( void ); > + > #ifdef __cplusplus > } > #endif > -- > 1.8.1.4 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel