> -----Original Message----- > From: ged...@gwmail.gwu.edu [mailto:ged...@gwmail.gwu.edu] On > Behalf Of Gedare Bloom > Sent: Tuesday, November 04, 2014 10:16 AM > To: Jennifer Averett > Cc: rtems-de...@rtems.org > Subject: Re: [PATCH 2/4] capture: Add SMP support. > > 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.
Removed > > /* > > * 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. Removed from capture-cli.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.) Removed the _t identifier. > > +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? The capture lock was broken into a global lock and a per-cpu lock. We didn't want to lock cpu's 1-3 to add records to cpu 0. I can name capture_lock_global capture_lock if that is what you are suggesting. > > /* > > * 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? It should be fine. The only problem that was mentioned in the past was that we couldn't malloc or workspace_allocate during a task switch. That was resolved with the previous sets of patches. This method is initiated by a user call, not through user extension accesses. -- Jennifer > > - 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