[PATCH 2/4] capture: Add SMP support.
Gedare Bloom
gedare at rtems.org
Tue Nov 4 16:16:09 UTC 2014
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.
> /*
> * 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.
> /**
> * 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.)
> +static rtems_capture_per_cpu_data_t *capture_per_cpu = NULL;
> +
> +static rtems_capture_global_data_t capture_global;
>
> /*
> * RTEMS Capture Data.
> */
> -static rtems_capture_buffer_t capture_records = {NULL, 0, 0, 0, 0, 0};
> -static uint32_t capture_count;
> -static uint32_t capture_flags;
> -static rtems_capture_control_t* capture_controls;
> -static int capture_extension_index;
> -static rtems_capture_timestamp capture_timestamp;
> -static rtems_task_priority capture_ceiling;
> -static rtems_task_priority capture_floor;
> -static rtems_id capture_reader;
> -static rtems_interrupt_lock capture_lock =
> - RTEMS_INTERRUPT_LOCK_INITIALIZER("capture");
> +#define capture_per_cpu_get( _cpu ) \
> + ( &capture_per_cpu[ _cpu ] )
> +
> +#define capture_records_on_cpu( _cpu ) capture_per_cpu[ _cpu ].records
> +#define capture_count_on_cpu( _cpu ) capture_per_cpu[ _cpu ].count
> +#define capture_flags_on_cpu( _cpu ) capture_per_cpu[ _cpu ].flags
> +#define capture_reader_on_cpu( _cpu ) capture_per_cpu[ _cpu ].reader
> +#define capture_lock_on_cpu( _cpu ) capture_per_cpu[ _cpu ].lock
> +
> +#define capture_records capture_records_on_cpu( _SMP_Get_current_processor() )
> +#define capture_count capture_count_on_cpu( _SMP_Get_current_processor() )
> +#define capture_flags_per_cpu capture_flags_on_cpu( _SMP_Get_current_processor() )
> +#define capture_flags_global capture_global.flags
> +#define capture_controls capture_global.controls
> +#define capture_extension_index capture_global.extension_index
> +#define capture_timestamp capture_global.timestamp
> +#define capture_ceiling capture_global.ceiling
> +#define capture_floor capture_global.floor
> +#define capture_reader capture_reader_on_cpu( _SMP_Get_current_processor() )
> +#define capture_lock_per_cpu capture_lock_on_cpu( _SMP_Get_current_processor() )
> +#define capture_lock_global capture_global.lock
>
Why not define capture_lock?
> /*
> * RTEMS Event text.
> @@ -108,12 +139,12 @@ int rtems_capture_get_extension_index(void)
>
> uint32_t rtems_capture_get_flags(void)
> {
> - return capture_flags;
> + return capture_flags_global;
> }
>
> void rtems_capture_set_flags(uint32_t mask)
> {
> - capture_flags |= mask;
> + capture_flags_global |= mask;
> }
>
> /*
> @@ -284,11 +315,11 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
>
> if (control == NULL)
> {
> - bool ok = rtems_workspace_allocate (sizeof (*control), (void **) &control);
> + control = malloc( sizeof (*control));
>
These functional changes would be better presented as a separate
commit if that makes sense. Was it agreed that replacing the
workspace_allocate() with malloc() is OK here?
> - if (!ok)
> + if (!control)
> {
> - capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
> + capture_flags_global |= RTEMS_CAPTURE_NO_MEMORY;
> return NULL;
> }
>
> @@ -301,13 +332,13 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
>
> memset (control->by, 0, sizeof (control->by));
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> control->next = capture_controls;
> capture_controls = control;
> rtems_iterate_over_all_threads (rtems_capture_initialize_control);
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> }
>
> return control;
> @@ -315,16 +346,18 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
>
> void rtems_capture_initialize_task( rtems_tcb* tcb )
> {
> - rtems_capture_control_t* control;
> - rtems_name name;
> + rtems_capture_control_t* control;
> + rtems_name name;
> + rtems_interrupt_lock_context lock_context;
>
> /*
> - * We need to scan the default control list to initialise
> + * We need to scan the default control list to initialize
> * this control if it is a new task.
> */
>
> rtems_object_get_classic_name( tcb->Object.id, &name );
>
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
> if (tcb->Capture.control == NULL) {
> for (control = capture_controls; control != NULL; control = control->next)
> if (rtems_capture_match_name_id (control->name, control->id,
> @@ -333,28 +366,31 @@ void rtems_capture_initialize_task( rtems_tcb* tcb )
> }
>
> tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK;
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> }
>
> void rtems_capture_record_task( rtems_tcb* tcb )
> {
> rtems_capture_task_record_t rec;
> void* ptr;
> + rtems_interrupt_lock_context lock_context;
>
> rtems_object_get_classic_name( tcb->Object.id, &rec.name );
> -
> +
> rec.stack_size = tcb->Start.Initial_stack.size;
> rec.start_priority = _RTEMS_tasks_Priority_from_Core(
> tcb->Start.initial_priority
> );
>
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
> tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK;
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> /*
> * Log the task information. The first time a task is
> * seen a record is logged. This record can be identified
> * by a 0 in the event identifier.
> */
> -
> rtems_capture_begin_add_record (tcb, 0, sizeof(rec), &ptr);
> ptr = rtems_capture_append_to_record(
> ptr,
> @@ -375,14 +411,14 @@ void rtems_capture_record_task( rtems_tcb* tcb )
> }
>
> /*
> - * This function indicates if data should be filtered from the
> + * This function indicates if data should be filtered from the
> * log.
> */
> bool rtems_capture_filter( rtems_tcb* tcb,
> uint32_t events)
> {
> if (tcb &&
> - ((capture_flags &
> + ((capture_flags_global &
> (RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
> RTEMS_CAPTURE_TRIGGERED))
> {
> @@ -398,7 +434,7 @@ bool rtems_capture_filter( rtems_tcb* tcb,
> if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
> ((tcb->real_priority >= capture_ceiling) &&
> (tcb->real_priority <= capture_floor) &&
> - ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
> + ((capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH) ||
> (control && (control->flags & RTEMS_CAPTURE_WATCH)))))
> {
> return false;
> @@ -420,7 +456,7 @@ rtems_capture_record_open (rtems_tcb* tcb,
> uint8_t* ptr;
> rtems_capture_record_t* capture_in;
>
> - rtems_interrupt_lock_acquire (&capture_lock, lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_per_cpu, lock_context);
>
> ptr = rtems_capture_buffer_allocate(&capture_records, size);
> capture_in = (rtems_capture_record_t *) ptr;
> @@ -441,14 +477,14 @@ rtems_capture_record_open (rtems_tcb* tcb,
> ptr = ptr + sizeof(*capture_in);
> }
> else
> - capture_flags |= RTEMS_CAPTURE_OVERFLOW;
> + capture_flags_per_cpu |= RTEMS_CAPTURE_OVERFLOW;
>
> return ptr;
> }
>
> void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* lock_context)
> {
> - rtems_interrupt_lock_release (&capture_lock, lock_context);
> + rtems_interrupt_lock_release (&capture_lock_per_cpu, lock_context);
> }
>
> /*
> @@ -460,11 +496,10 @@ rtems_capture_trigger (rtems_tcb* ft,
> rtems_tcb* tt,
> uint32_t events)
> {
> -
> /*
> * If we have not triggered then see if this is a trigger condition.
> */
> - if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED))
> + if (!(capture_flags_global & RTEMS_CAPTURE_TRIGGERED))
> {
> rtems_capture_control_t* fc = NULL;
> rtems_capture_control_t* tc = NULL;
> @@ -499,7 +534,7 @@ rtems_capture_trigger (rtems_tcb* ft,
> */
> if (from_events || to_events)
> {
> - capture_flags |= RTEMS_CAPTURE_TRIGGERED;
> + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
> return 1;
> }
>
> @@ -510,7 +545,7 @@ rtems_capture_trigger (rtems_tcb* ft,
> {
> if (rtems_capture_by_in_to (events, ft, tc))
> {
> - capture_flags |= RTEMS_CAPTURE_TRIGGERED;
> + capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
> return 1;
> }
> }
> @@ -523,47 +558,61 @@ rtems_capture_trigger (rtems_tcb* ft,
>
> /*
> * This function initialises the realtime capture engine allocating the trace
> - * buffer. It is assumed we have a working heap at stage of initialisation.
> + * buffer. It is assumed we have a working heap at stage of initialization.
> */
> rtems_status_code
> rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribute__((unused)))
> {
> - rtems_status_code sc;
> + rtems_status_code sc = RTEMS_SUCCESSFUL;
> + size_t count;
> + uint32_t i;
> + rtems_capture_buffer_t* buff;
>
> /*
> * See if the capture engine is already open.
> */
>
> - if (capture_records.buffer)
> + if ((capture_flags_global & RTEMS_CAPTURE_INIT) == RTEMS_CAPTURE_INIT) {
> return RTEMS_RESOURCE_IN_USE;
> + }
>
> - rtems_capture_buffer_create( &capture_records, size );
> + count = rtems_get_processor_count();
> + if (capture_per_cpu == NULL) {
> + capture_per_cpu = calloc( count, sizeof(rtems_capture_per_cpu_data_t) );
> + }
>
> - if (capture_records.buffer == NULL)
> - return RTEMS_NO_MEMORY;
> + for (i=0; i<count; i++) {
> + buff = &capture_records_on_cpu(i);
> + rtems_capture_buffer_create( buff, size );
> + if (buff->buffer == NULL) {
> + sc = RTEMS_NO_MEMORY;
> + break;
> + }
>
> - capture_count = 0;
> - capture_flags = 0;
> + capture_count_on_cpu(i) = 0;
> + capture_flags_on_cpu(i) = 0;
> + }
> +
> + capture_flags_global = 0;
> capture_ceiling = 0;
> capture_floor = 255;
> -
> - sc = rtems_capture_user_extension_open();
> + if (sc == RTEMS_SUCCESSFUL)
> + sc = rtems_capture_user_extension_open();
>
> if (sc != RTEMS_SUCCESSFUL)
> {
> - rtems_capture_buffer_destroy( &capture_records);
> + for (i=0; i<count; i++)
> + rtems_capture_buffer_destroy( &capture_records_on_cpu(i));
> + } else {
> + capture_flags_global |= RTEMS_CAPTURE_INIT;
> }
>
> - /*
> - * Iterate over the list of existing tasks.
> - */
> -
> return sc;
> }
>
> /*
> * This function shutdowns the capture engine and release any claimed
> - * resources.
> + * resources. Capture control must be disabled prior to calling a close.
> */
> rtems_status_code
> rtems_capture_close (void)
> @@ -571,18 +620,26 @@ rtems_capture_close (void)
> rtems_interrupt_lock_context lock_context;
> rtems_capture_control_t* control;
> rtems_status_code sc;
> + uint32_t cpu;
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> - if (!capture_records.buffer)
> + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
> {
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> return RTEMS_SUCCESSFUL;
> }
>
> - capture_flags &= ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR);
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> + {
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> + return RTEMS_UNSATISFIED;
> + }
> +
> + capture_flags_global &=
> + ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR | RTEMS_CAPTURE_INIT);
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> /*
> * Delete the extension first. This means we are now able to
> @@ -600,16 +657,19 @@ rtems_capture_close (void)
> {
> rtems_capture_control_t* delete = control;
> control = control->next;
> - rtems_workspace_free (delete);
> + free (delete);
> }
>
> capture_controls = NULL;
> -
> - if (capture_records.buffer)
> - {
> - rtems_capture_buffer_destroy( &capture_records);
> + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) {
> + capture_count_on_cpu(cpu) = 0;
> + if (capture_records_on_cpu(cpu).buffer)
> + rtems_capture_buffer_destroy( &capture_records_on_cpu(cpu) );
> }
>
> + free( capture_per_cpu );
> + capture_per_cpu = NULL;
> +
> return RTEMS_SUCCESSFUL;
> }
>
> @@ -618,20 +678,20 @@ rtems_capture_control (bool enable)
> {
> rtems_interrupt_lock_context lock_context;
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> - if (!capture_records.buffer)
> + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
> {
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> return RTEMS_UNSATISFIED;
> }
>
> if (enable)
> - capture_flags |= RTEMS_CAPTURE_ON;
> + capture_flags_global |= RTEMS_CAPTURE_ON;
> else
> - capture_flags &= ~RTEMS_CAPTURE_ON;
> + capture_flags_global &= ~RTEMS_CAPTURE_ON;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> return RTEMS_SUCCESSFUL;
> }
> @@ -646,20 +706,20 @@ rtems_capture_monitor (bool enable)
> {
> rtems_interrupt_lock_context lock_context;
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> - if (!capture_records.buffer)
> + if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
> {
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
> return RTEMS_UNSATISFIED;
> }
>
> if (enable)
> - capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR;
> + capture_flags_global |= RTEMS_CAPTURE_ONLY_MONITOR;
> else
> - capture_flags &= ~RTEMS_CAPTURE_ONLY_MONITOR;
> + capture_flags_global &= ~RTEMS_CAPTURE_ONLY_MONITOR;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> return RTEMS_SUCCESSFUL;
> }
> @@ -673,7 +733,6 @@ rtems_capture_flush_tcb (rtems_tcb *tcb)
> tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED;
> }
>
> -
> /*
> * This function flushes the capture buffer. The prime parameter allows the
> * capture engine to also be primed again.
> @@ -681,21 +740,36 @@ rtems_capture_flush_tcb (rtems_tcb *tcb)
> rtems_status_code
> rtems_capture_flush (bool prime)
> {
> - rtems_interrupt_lock_context lock_context;
> + rtems_interrupt_lock_context lock_context_global;
> + rtems_interrupt_lock_context lock_context_per_cpu;
> + rtems_interrupt_lock* lock;
> + uint32_t cpu;
> +
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context_global);
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> + {
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global);
> + return RTEMS_UNSATISFIED;
> + }
>
> rtems_iterate_over_all_threads (rtems_capture_flush_tcb);
>
> if (prime)
> - capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
> + capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
> else
> - capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
> -
> - rtems_capture_buffer_flush( &capture_records );
> - capture_count = 0;
> + capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW;
> +
> + for (cpu=0; cpu < rtems_get_processor_count(); cpu++) {
> + lock = &(capture_lock_on_cpu( cpu ));
> + rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu);
> + capture_count_on_cpu(cpu) = 0;
> + if (capture_records_on_cpu(cpu).buffer)
> + rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) );
> + rtems_interrupt_lock_release (lock, &lock_context_per_cpu);
> + }
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global);
>
> return RTEMS_SUCCESSFUL;
> }
> @@ -704,13 +778,16 @@ rtems_capture_flush (bool prime)
> * This function defines a watch for a specific task given a name. A watch
> * causes it to be traced either in or out of context. The watch can be
> * optionally enabled or disabled with the set routine. It is disabled by
> - * default.
> + * default. A watch can only be defined when capture control is disabled
> */
> rtems_status_code
> rtems_capture_watch_add (rtems_name name, rtems_id id)
> {
> rtems_capture_control_t* control;
>
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> + return RTEMS_UNSATISFIED;
> +
> if ((name == 0) && (id == 0))
> return RTEMS_UNSATISFIED;
>
> @@ -731,7 +808,8 @@ rtems_capture_watch_add (rtems_name name, rtems_id id)
> /*
> * This function removes a watch for a specific task given a name. The task
> * description will still exist if referenced by a trace record in the trace
> - * buffer or a global watch is defined.
> + * buffer or a global watch is defined. A watch can only be deleted when
> + * capture control is disabled.
> */
> rtems_status_code
> rtems_capture_watch_del (rtems_name name, rtems_id id)
> @@ -741,6 +819,9 @@ rtems_capture_watch_del (rtems_name name, rtems_id id)
> rtems_capture_control_t** prev_control;
> bool found = false;
>
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> + return RTEMS_UNSATISFIED;
> +
> /*
> * Should this test be for wildcards ?
> */
> @@ -750,13 +831,13 @@ rtems_capture_watch_del (rtems_name name, rtems_id id)
> {
> if (rtems_capture_match_name_id (control->name, control->id, name, id))
> {
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> *prev_control = control->next;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> - rtems_workspace_free (control);
> + free (control);
>
> control = *prev_control;
>
> @@ -786,6 +867,9 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable)
> rtems_capture_control_t* control;
> bool found = false;
>
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> + return RTEMS_UNSATISFIED;
> +
> /*
> * Find the control and then set the watch. It must exist before it can
> * be controlled.
> @@ -794,14 +878,14 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable)
> {
> if (rtems_capture_match_name_id (control->name, control->id, name, id))
> {
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> if (enable)
> control->flags |= RTEMS_CAPTURE_WATCH;
> else
> control->flags &= ~RTEMS_CAPTURE_WATCH;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> found = true;
> }
> @@ -823,18 +907,18 @@ rtems_capture_watch_global (bool enable)
> {
> rtems_interrupt_lock_context lock_context;
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
>
> /*
> * We need to keep specific and global watches separate so
> * a global enable/disable does not lose a specific watch.
> */
> if (enable)
> - capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
> + capture_flags_global |= RTEMS_CAPTURE_GLOBAL_WATCH;
> else
> - capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
> + capture_flags_global &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
>
> return RTEMS_SUCCESSFUL;
> }
> @@ -845,7 +929,7 @@ rtems_capture_watch_global (bool enable)
> bool
> rtems_capture_watch_global_on (void)
> {
> - return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
> + return capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
> }
>
> /*
> @@ -1082,30 +1166,26 @@ rtems_capture_clear_trigger (rtems_name from_name,
> }
>
> static inline uint32_t rtems_capture_count_records( void* recs, size_t size )
> -{
> +{
> rtems_capture_record_t* rec;
> uint8_t* ptr = recs;
> uint32_t rec_count = 0;
> size_t byte_count = 0;
> -
> -
> +
> +
> while (byte_count < size) {
> rec = (rtems_capture_record_t*) ptr;
> rec_count++;
> _Assert( rec->size >= sizeof(*rec) );
> ptr += rec->size;
> byte_count += rec->size;
> - _Assert( rec_count <= capture_count );
> };
> -
> +
> return rec_count;
> }
>
> /*
> * This function reads a number of records from the capture buffer.
> - * The user can optionally block and wait until the buffer as a
> - * specific number of records available or a specific time has
> - * elasped.
> *
> * The function returns the number of record that is has that are
> * in a continous block of memory. If the number of available records
> @@ -1117,106 +1197,47 @@ static inline uint32_t rtems_capture_count_records( void* recs, size_t size )
> * The user must release the records. This is achieved with a call to
> * rtems_capture_release. Calls this function without a release will
> * result in at least the same number of records being released.
> - *
> - * The 'threshold' parameter is the number of records that must be
> - * captured before returning. If a timeout period is specified (non-0)
> - * any captured records will be returned. These parameters stop
> - * thrashing occuring for a small number of records, yet allows
> - * a user configured latiency to be applied for single events.
> - *
> - * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
> - * the timeout.
> */
> rtems_status_code
> -rtems_capture_read (uint32_t threshold,
> - uint32_t timeout,
> +rtems_capture_read (uint32_t cpu,
> uint32_t* read,
> rtems_capture_record_t** recs)
> {
> rtems_interrupt_lock_context lock_context;
> rtems_status_code sc = RTEMS_SUCCESSFUL;
> size_t recs_size = 0;
> - bool wrapped;
> + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu ));
> + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu ));
> + uint32_t* flags = &(capture_flags_on_cpu( cpu ));
>
> *read = 0;
> *recs = NULL;
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (lock, &lock_context);
>
> /*
> * Only one reader is allowed.
> */
>
> - if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE)
> + if (*flags & RTEMS_CAPTURE_READER_ACTIVE)
> {
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (lock, &lock_context);
> return RTEMS_RESOURCE_IN_USE;
> }
>
> - capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
> -
> - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size );
> - *read = rtems_capture_count_records( *recs, recs_size );
> -
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> -
> - for (;;)
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
> {
> - /*
> - * See if the data wraps the end of the record buffer.
> - */
> - wrapped = rtems_capture_buffer_has_wrapped( &capture_records);
> -
> - /*
> - * Do we have a threshold and have not wrapped
> - * around the end of the capture record buffer ?
> - */
> - if ((!wrapped) && threshold)
> - {
> - /*
> - * Do we have enough records ?
> - */
> - if (*read < threshold)
> - {
> - rtems_event_set event_out;
> -
> - rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader);
> -
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> -
> - capture_flags |= RTEMS_CAPTURE_READER_WAITING;
> -
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> -
> - sc = rtems_event_receive (RTEMS_EVENT_0,
> - RTEMS_WAIT | RTEMS_EVENT_ANY,
> - RTEMS_MICROSECONDS_TO_TICKS (timeout),
> - &event_out);
> -
> - /*
> - * Let the user handle all other sorts of errors. This may
> - * not be the best solution, but oh well, it will do for
> - * now.
> - */
> - if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT))
> - break;
> -
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (lock, &lock_context);
> + return RTEMS_UNSATISFIED;
> + }
>
> - *recs = rtems_capture_buffer_peek( &capture_records, &recs_size );
> - *read = rtems_capture_count_records( *recs, recs_size );
> + *flags |= RTEMS_CAPTURE_READER_ACTIVE;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + *recs = rtems_capture_buffer_peek( records, &recs_size );
>
> - continue;
> - }
> - }
> + *read = rtems_capture_count_records( *recs, recs_size );
>
> - /*
> - * Always out if we reach here. To loop use continue.
> - */
> - break;
> - }
> + rtems_interrupt_lock_release (lock, &lock_context);
>
> return sc;
> }
> @@ -1226,7 +1247,7 @@ rtems_capture_read (uint32_t threshold,
> * to the capture engine. The count must match the number read.
> */
> rtems_status_code
> -rtems_capture_release (uint32_t count)
> +rtems_capture_release (uint32_t cpu, uint32_t count)
> {
> rtems_interrupt_lock_context lock_context;
> uint8_t* ptr;
> @@ -1235,43 +1256,49 @@ rtems_capture_release (uint32_t count)
> size_t ptr_size = 0;
> size_t rel_size = 0;
> rtems_status_code ret_val = RTEMS_SUCCESSFUL;
> + rtems_interrupt_lock* lock = &(capture_lock_on_cpu( cpu ));
> + rtems_capture_buffer_t* records = &(capture_records_on_cpu( cpu ));
> + uint32_t* flags = &(capture_flags_on_cpu( cpu ));
> + uint32_t* total = &(capture_count_on_cpu( cpu ));
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> + rtems_interrupt_lock_acquire (lock, &lock_context);
>
> - if (count > capture_count)
> - count = capture_count;
> + if (count > *total) {
> + count = *total;
> + }
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) {
> + rtems_interrupt_lock_release (lock, &lock_context);
> + return RTEMS_UNSATISFIED;
> + }
>
> counted = count;
> -
> - ptr = rtems_capture_buffer_peek( &capture_records, &ptr_size );
> +
> + ptr = rtems_capture_buffer_peek( records, &ptr_size );
> _Assert(ptr_size >= (count * sizeof(*rec) ));
>
> rel_size = 0;
> - while (counted--)
> - {
> + while (counted--) {
> rec = (rtems_capture_record_t*) ptr;
> rel_size += rec->size;
> _Assert( rel_size <= ptr_size );
> ptr += rec->size;
> }
>
> - rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
> -
> if (rel_size > ptr_size ) {
> ret_val = RTEMS_INVALID_NUMBER;
> rel_size = ptr_size;
> }
>
> - capture_count -= count;
> + *total -= count;
>
> - if (count)
> - rtems_capture_buffer_free( &capture_records, rel_size );
> + if (count) {
> + rtems_capture_buffer_free( records, rel_size );
> + }
>
> - capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
> + *flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
>
> - rtems_interrupt_lock_release (&capture_lock, &lock_context);
> + rtems_interrupt_lock_release (lock, &lock_context);
>
> return ret_val;
> }
> @@ -1308,5 +1335,3 @@ rtems_capture_get_control_list (void)
> {
> return capture_controls;
> }
> -
> -
> diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
> index f907686..63d1343 100644
> --- a/cpukit/libmisc/capture/capture.h
> +++ b/cpukit/libmisc/capture/capture.h
> @@ -15,7 +15,7 @@
> All rights reserved Objective Design Systems Pty Ltd, 2002
> Chris Johns (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