[PATCH 2/4] capture: Add SMP support.
Jennifer Averett
Jennifer.Averett at OARcorp.com
Tue Nov 4 16:36:56 UTC 2014
> -----Original Message-----
> From: gedare at gwmail.gwu.edu [mailto:gedare at gwmail.gwu.edu] On
> Behalf Of Gedare Bloom
> Sent: Tuesday, November 04, 2014 10:16 AM
> To: Jennifer Averett
> Cc: rtems-devel at 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.averett at 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 (ccj at 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 (ccj at 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 (ccj at 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 (ccj at 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 (ccj at 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 (ccj at 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 at rtems.org
> > http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list