[PATCH 3/6] capture: Add SMP support.
Jennifer Averett
jennifer.averett at oarcorp.com
Thu Nov 20 21:05:21 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.
---
cpukit/libmisc/capture/capture.c | 411 +++++++++++++++++++----------------
cpukit/libmisc/capture/capture.h | 22 +-
cpukit/libmisc/capture/captureimpl.h | 19 +-
3 files changed, 234 insertions(+), 218 deletions(-)
diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c
index a83bc90..4327100 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;
+
+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;
+
+static rtems_capture_per_cpu_data *capture_per_cpu = NULL;
+
+static rtems_capture_global_data 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) );
+ }
- 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..c8bc270 100644
--- a/cpukit/libmisc/capture/capture.h
+++ b/cpukit/libmisc/capture/capture.h
@@ -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.
diff --git a/cpukit/libmisc/capture/captureimpl.h b/cpukit/libmisc/capture/captureimpl.h
index cc11646..44d81db 100644
--- a/cpukit/libmisc/capture/captureimpl.h
+++ b/cpukit/libmisc/capture/captureimpl.h
@@ -43,14 +43,19 @@ 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.
--
1.8.1.4
More information about the devel
mailing list