[PATCH 2/4] capture: Add SMP support.

Jennifer Averett jennifer.averett at oarcorp.com
Tue Nov 4 13:39:09 UTC 2014


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;
+
 /*
  * 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>
 
 /**
  * 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;
+
+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
 
 /*
  * 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));
 
-    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



More information about the devel mailing list