forked from Imagelibrary/rtems
capture: Add SMP support.
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.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
All rights reserved Objective Design Systems Pty Ltd, 2002
|
All rights reserved Objective Design Systems Pty Ltd, 2002
|
||||||
Chris Johns (ccj@acm.org)
|
Chris Johns (ccj@acm.org)
|
||||||
|
|
||||||
COPYRIGHT (c) 1989-2009.
|
COPYRIGHT (c) 1989-2014.
|
||||||
On-Line Applications Research Corporation (OAR).
|
On-Line Applications Research Corporation (OAR).
|
||||||
|
|
||||||
The license and distribution terms for this file may be
|
The license and distribution terms for this file may be
|
||||||
@@ -59,21 +59,52 @@
|
|||||||
#define RTEMS_CAPTURE_RECORD_EVENTS (0)
|
#define RTEMS_CAPTURE_RECORD_EVENTS (0)
|
||||||
#endif
|
#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.
|
* RTEMS Capture Data.
|
||||||
*/
|
*/
|
||||||
static rtems_capture_buffer_t capture_records = {NULL, 0, 0, 0, 0, 0};
|
#define capture_per_cpu_get( _cpu ) \
|
||||||
static uint32_t capture_count;
|
( &capture_per_cpu[ _cpu ] )
|
||||||
static uint32_t capture_flags;
|
|
||||||
static rtems_capture_control_t* capture_controls;
|
#define capture_records_on_cpu( _cpu ) capture_per_cpu[ _cpu ].records
|
||||||
static int capture_extension_index;
|
#define capture_count_on_cpu( _cpu ) capture_per_cpu[ _cpu ].count
|
||||||
static rtems_capture_timestamp capture_timestamp;
|
#define capture_flags_on_cpu( _cpu ) capture_per_cpu[ _cpu ].flags
|
||||||
static rtems_task_priority capture_ceiling;
|
#define capture_reader_on_cpu( _cpu ) capture_per_cpu[ _cpu ].reader
|
||||||
static rtems_task_priority capture_floor;
|
#define capture_lock_on_cpu( _cpu ) capture_per_cpu[ _cpu ].lock
|
||||||
static rtems_id capture_reader;
|
|
||||||
static rtems_interrupt_lock capture_lock =
|
#define capture_records capture_records_on_cpu( _SMP_Get_current_processor() )
|
||||||
RTEMS_INTERRUPT_LOCK_INITIALIZER("capture");
|
#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.
|
* RTEMS Event text.
|
||||||
@@ -108,12 +139,12 @@ int rtems_capture_get_extension_index(void)
|
|||||||
|
|
||||||
uint32_t rtems_capture_get_flags(void)
|
uint32_t rtems_capture_get_flags(void)
|
||||||
{
|
{
|
||||||
return capture_flags;
|
return capture_flags_global;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtems_capture_set_flags(uint32_t mask)
|
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)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,13 +332,13 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
|
|||||||
|
|
||||||
memset (control->by, 0, sizeof (control->by));
|
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;
|
control->next = capture_controls;
|
||||||
capture_controls = control;
|
capture_controls = control;
|
||||||
rtems_iterate_over_all_threads (rtems_capture_initialize_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;
|
return control;
|
||||||
@@ -315,16 +346,18 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
|
|||||||
|
|
||||||
void rtems_capture_initialize_task( rtems_tcb* tcb )
|
void rtems_capture_initialize_task( rtems_tcb* tcb )
|
||||||
{
|
{
|
||||||
rtems_capture_control_t* control;
|
rtems_capture_control_t* control;
|
||||||
rtems_name name;
|
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.
|
* this control if it is a new task.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rtems_object_get_classic_name( tcb->Object.id, &name );
|
rtems_object_get_classic_name( tcb->Object.id, &name );
|
||||||
|
|
||||||
|
rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
|
||||||
if (tcb->Capture.control == NULL) {
|
if (tcb->Capture.control == NULL) {
|
||||||
for (control = capture_controls; control != NULL; control = control->next)
|
for (control = capture_controls; control != NULL; control = control->next)
|
||||||
if (rtems_capture_match_name_id (control->name, control->id,
|
if (rtems_capture_match_name_id (control->name, control->id,
|
||||||
@@ -333,12 +366,14 @@ void rtems_capture_initialize_task( rtems_tcb* tcb )
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK;
|
tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK;
|
||||||
|
rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtems_capture_record_task( rtems_tcb* tcb )
|
void rtems_capture_record_task( rtems_tcb* tcb )
|
||||||
{
|
{
|
||||||
rtems_capture_task_record_t rec;
|
rtems_capture_task_record_t rec;
|
||||||
void* ptr;
|
void* ptr;
|
||||||
|
rtems_interrupt_lock_context lock_context;
|
||||||
|
|
||||||
rtems_object_get_classic_name( tcb->Object.id, &rec.name );
|
rtems_object_get_classic_name( tcb->Object.id, &rec.name );
|
||||||
|
|
||||||
@@ -347,14 +382,15 @@ void rtems_capture_record_task( rtems_tcb* tcb )
|
|||||||
tcb->Start.initial_priority
|
tcb->Start.initial_priority
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
|
||||||
tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK;
|
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
|
* Log the task information. The first time a task is
|
||||||
* seen a record is logged. This record can be identified
|
* seen a record is logged. This record can be identified
|
||||||
* by a 0 in the event identifier.
|
* by a 0 in the event identifier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rtems_capture_begin_add_record (tcb, 0, sizeof(rec), &ptr);
|
rtems_capture_begin_add_record (tcb, 0, sizeof(rec), &ptr);
|
||||||
ptr = rtems_capture_append_to_record(
|
ptr = rtems_capture_append_to_record(
|
||||||
ptr,
|
ptr,
|
||||||
@@ -382,7 +418,7 @@ bool rtems_capture_filter( rtems_tcb* tcb,
|
|||||||
uint32_t events)
|
uint32_t events)
|
||||||
{
|
{
|
||||||
if (tcb &&
|
if (tcb &&
|
||||||
((capture_flags &
|
((capture_flags_global &
|
||||||
(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
|
(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
|
||||||
RTEMS_CAPTURE_TRIGGERED))
|
RTEMS_CAPTURE_TRIGGERED))
|
||||||
{
|
{
|
||||||
@@ -398,7 +434,7 @@ bool rtems_capture_filter( rtems_tcb* tcb,
|
|||||||
if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
|
if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
|
||||||
((tcb->real_priority >= capture_ceiling) &&
|
((tcb->real_priority >= capture_ceiling) &&
|
||||||
(tcb->real_priority <= capture_floor) &&
|
(tcb->real_priority <= capture_floor) &&
|
||||||
((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
|
((capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH) ||
|
||||||
(control && (control->flags & RTEMS_CAPTURE_WATCH)))))
|
(control && (control->flags & RTEMS_CAPTURE_WATCH)))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -420,7 +456,7 @@ rtems_capture_record_open (rtems_tcb* tcb,
|
|||||||
uint8_t* ptr;
|
uint8_t* ptr;
|
||||||
rtems_capture_record_t* capture_in;
|
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);
|
ptr = rtems_capture_buffer_allocate(&capture_records, size);
|
||||||
capture_in = (rtems_capture_record_t *) ptr;
|
capture_in = (rtems_capture_record_t *) ptr;
|
||||||
@@ -441,14 +477,14 @@ rtems_capture_record_open (rtems_tcb* tcb,
|
|||||||
ptr = ptr + sizeof(*capture_in);
|
ptr = ptr + sizeof(*capture_in);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
capture_flags |= RTEMS_CAPTURE_OVERFLOW;
|
capture_flags_per_cpu |= RTEMS_CAPTURE_OVERFLOW;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* lock_context)
|
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,
|
rtems_tcb* tt,
|
||||||
uint32_t events)
|
uint32_t events)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have not triggered then see if this is a trigger condition.
|
* 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* fc = NULL;
|
||||||
rtems_capture_control_t* tc = NULL;
|
rtems_capture_control_t* tc = NULL;
|
||||||
@@ -499,7 +534,7 @@ rtems_capture_trigger (rtems_tcb* ft,
|
|||||||
*/
|
*/
|
||||||
if (from_events || to_events)
|
if (from_events || to_events)
|
||||||
{
|
{
|
||||||
capture_flags |= RTEMS_CAPTURE_TRIGGERED;
|
capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +545,7 @@ rtems_capture_trigger (rtems_tcb* ft,
|
|||||||
{
|
{
|
||||||
if (rtems_capture_by_in_to (events, ft, tc))
|
if (rtems_capture_by_in_to (events, ft, tc))
|
||||||
{
|
{
|
||||||
capture_flags |= RTEMS_CAPTURE_TRIGGERED;
|
capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,47 +558,61 @@ rtems_capture_trigger (rtems_tcb* ft,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This function initialises the realtime capture engine allocating the trace
|
* 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_status_code
|
||||||
rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribute__((unused)))
|
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.
|
* 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;
|
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)
|
for (i=0; i<count; i++) {
|
||||||
return RTEMS_NO_MEMORY;
|
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_count_on_cpu(i) = 0;
|
||||||
capture_flags = 0;
|
capture_flags_on_cpu(i) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
capture_flags_global = 0;
|
||||||
capture_ceiling = 0;
|
capture_ceiling = 0;
|
||||||
capture_floor = 255;
|
capture_floor = 255;
|
||||||
|
if (sc == RTEMS_SUCCESSFUL)
|
||||||
sc = rtems_capture_user_extension_open();
|
sc = rtems_capture_user_extension_open();
|
||||||
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
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;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function shutdowns the capture engine and release any claimed
|
* 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_status_code
|
||||||
rtems_capture_close (void)
|
rtems_capture_close (void)
|
||||||
@@ -571,18 +620,26 @@ rtems_capture_close (void)
|
|||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
rtems_capture_control_t* control;
|
rtems_capture_control_t* control;
|
||||||
rtems_status_code sc;
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
capture_flags_global &=
|
||||||
|
~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR | RTEMS_CAPTURE_INIT);
|
||||||
|
|
||||||
|
rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete the extension first. This means we are now able to
|
* 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;
|
rtems_capture_control_t* delete = control;
|
||||||
control = control->next;
|
control = control->next;
|
||||||
rtems_workspace_free (delete);
|
free (delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_controls = NULL;
|
capture_controls = NULL;
|
||||||
|
for (cpu=0; cpu < rtems_get_processor_count(); cpu++) {
|
||||||
if (capture_records.buffer)
|
capture_count_on_cpu(cpu) = 0;
|
||||||
{
|
if (capture_records_on_cpu(cpu).buffer)
|
||||||
rtems_capture_buffer_destroy( &capture_records);
|
rtems_capture_buffer_destroy( &capture_records_on_cpu(cpu) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free( capture_per_cpu );
|
||||||
|
capture_per_cpu = NULL;
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,20 +678,20 @@ rtems_capture_control (bool enable)
|
|||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
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;
|
return RTEMS_UNSATISFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
capture_flags |= RTEMS_CAPTURE_ON;
|
capture_flags_global |= RTEMS_CAPTURE_ON;
|
||||||
else
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -646,20 +706,20 @@ rtems_capture_monitor (bool enable)
|
|||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
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;
|
return RTEMS_UNSATISFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
capture_flags |= RTEMS_CAPTURE_ONLY_MONITOR;
|
capture_flags_global |= RTEMS_CAPTURE_ONLY_MONITOR;
|
||||||
else
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -673,7 +733,6 @@ rtems_capture_flush_tcb (rtems_tcb *tcb)
|
|||||||
tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED;
|
tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function flushes the capture buffer. The prime parameter allows the
|
* This function flushes the capture buffer. The prime parameter allows the
|
||||||
* capture engine to also be primed again.
|
* capture engine to also be primed again.
|
||||||
@@ -681,21 +740,36 @@ rtems_capture_flush_tcb (rtems_tcb *tcb)
|
|||||||
rtems_status_code
|
rtems_status_code
|
||||||
rtems_capture_flush (bool prime)
|
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, &lock_context);
|
rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context_global);
|
||||||
|
|
||||||
|
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);
|
rtems_iterate_over_all_threads (rtems_capture_flush_tcb);
|
||||||
|
|
||||||
if (prime)
|
if (prime)
|
||||||
capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
|
capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
|
||||||
else
|
else
|
||||||
capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
|
capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW;
|
||||||
|
|
||||||
rtems_capture_buffer_flush( &capture_records );
|
for (cpu=0; cpu < rtems_get_processor_count(); cpu++) {
|
||||||
capture_count = 0;
|
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;
|
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
|
* 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
|
* 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
|
* 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_status_code
|
||||||
rtems_capture_watch_add (rtems_name name, rtems_id id)
|
rtems_capture_watch_add (rtems_name name, rtems_id id)
|
||||||
{
|
{
|
||||||
rtems_capture_control_t* control;
|
rtems_capture_control_t* control;
|
||||||
|
|
||||||
|
if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
|
||||||
|
return RTEMS_UNSATISFIED;
|
||||||
|
|
||||||
if ((name == 0) && (id == 0))
|
if ((name == 0) && (id == 0))
|
||||||
return RTEMS_UNSATISFIED;
|
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
|
* 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
|
* 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_status_code
|
||||||
rtems_capture_watch_del (rtems_name name, rtems_id id)
|
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;
|
rtems_capture_control_t** prev_control;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
|
||||||
|
return RTEMS_UNSATISFIED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Should this test be for wildcards ?
|
* 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))
|
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;
|
*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;
|
control = *prev_control;
|
||||||
|
|
||||||
@@ -786,6 +867,9 @@ rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable)
|
|||||||
rtems_capture_control_t* control;
|
rtems_capture_control_t* control;
|
||||||
bool found = false;
|
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
|
* Find the control and then set the watch. It must exist before it can
|
||||||
* be controlled.
|
* 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))
|
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)
|
if (enable)
|
||||||
control->flags |= RTEMS_CAPTURE_WATCH;
|
control->flags |= RTEMS_CAPTURE_WATCH;
|
||||||
else
|
else
|
||||||
control->flags &= ~RTEMS_CAPTURE_WATCH;
|
control->flags &= ~RTEMS_CAPTURE_WATCH;
|
||||||
|
|
||||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@@ -823,18 +907,18 @@ rtems_capture_watch_global (bool enable)
|
|||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
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
|
* We need to keep specific and global watches separate so
|
||||||
* a global enable/disable does not lose a specific watch.
|
* a global enable/disable does not lose a specific watch.
|
||||||
*/
|
*/
|
||||||
if (enable)
|
if (enable)
|
||||||
capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
|
capture_flags_global |= RTEMS_CAPTURE_GLOBAL_WATCH;
|
||||||
else
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -845,7 +929,7 @@ rtems_capture_watch_global (bool enable)
|
|||||||
bool
|
bool
|
||||||
rtems_capture_watch_global_on (void)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1095,7 +1179,6 @@ static inline uint32_t rtems_capture_count_records( void* recs, size_t size )
|
|||||||
_Assert( rec->size >= sizeof(*rec) );
|
_Assert( rec->size >= sizeof(*rec) );
|
||||||
ptr += rec->size;
|
ptr += rec->size;
|
||||||
byte_count += rec->size;
|
byte_count += rec->size;
|
||||||
_Assert( rec_count <= capture_count );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return rec_count;
|
return rec_count;
|
||||||
@@ -1103,9 +1186,6 @@ static inline uint32_t rtems_capture_count_records( void* recs, size_t size )
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This function reads a number of records from the 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
|
* The function returns the number of record that is has that are
|
||||||
* in a continous block of memory. If the number of available records
|
* 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
|
* The user must release the records. This is achieved with a call to
|
||||||
* rtems_capture_release. Calls this function without a release will
|
* rtems_capture_release. Calls this function without a release will
|
||||||
* result in at least the same number of records being released.
|
* 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_status_code
|
||||||
rtems_capture_read (uint32_t threshold,
|
rtems_capture_read (uint32_t cpu,
|
||||||
uint32_t timeout,
|
|
||||||
uint32_t* read,
|
uint32_t* read,
|
||||||
rtems_capture_record_t** recs)
|
rtems_capture_record_t** recs)
|
||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
size_t recs_size = 0;
|
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;
|
*read = 0;
|
||||||
*recs = NULL;
|
*recs = NULL;
|
||||||
|
|
||||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
rtems_interrupt_lock_acquire (lock, &lock_context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only one reader is allowed.
|
* 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;
|
return RTEMS_RESOURCE_IN_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
|
if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
|
||||||
|
{
|
||||||
|
rtems_interrupt_lock_release (lock, &lock_context);
|
||||||
|
return RTEMS_UNSATISFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*flags |= RTEMS_CAPTURE_READER_ACTIVE;
|
||||||
|
|
||||||
|
*recs = rtems_capture_buffer_peek( records, &recs_size );
|
||||||
|
|
||||||
*recs = rtems_capture_buffer_peek( &capture_records, &recs_size );
|
|
||||||
*read = rtems_capture_count_records( *recs, recs_size );
|
*read = rtems_capture_count_records( *recs, recs_size );
|
||||||
|
|
||||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
rtems_interrupt_lock_release (lock, &lock_context);
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
*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);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Always out if we reach here. To loop use continue.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
@@ -1226,7 +1247,7 @@ rtems_capture_read (uint32_t threshold,
|
|||||||
* to the capture engine. The count must match the number read.
|
* to the capture engine. The count must match the number read.
|
||||||
*/
|
*/
|
||||||
rtems_status_code
|
rtems_status_code
|
||||||
rtems_capture_release (uint32_t count)
|
rtems_capture_release (uint32_t cpu, uint32_t count)
|
||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
uint8_t* ptr;
|
uint8_t* ptr;
|
||||||
@@ -1235,43 +1256,49 @@ rtems_capture_release (uint32_t count)
|
|||||||
size_t ptr_size = 0;
|
size_t ptr_size = 0;
|
||||||
size_t rel_size = 0;
|
size_t rel_size = 0;
|
||||||
rtems_status_code ret_val = RTEMS_SUCCESSFUL;
|
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)
|
if (count > *total) {
|
||||||
count = capture_count;
|
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;
|
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) ));
|
_Assert(ptr_size >= (count * sizeof(*rec) ));
|
||||||
|
|
||||||
rel_size = 0;
|
rel_size = 0;
|
||||||
while (counted--)
|
while (counted--) {
|
||||||
{
|
|
||||||
rec = (rtems_capture_record_t*) ptr;
|
rec = (rtems_capture_record_t*) ptr;
|
||||||
rel_size += rec->size;
|
rel_size += rec->size;
|
||||||
_Assert( rel_size <= ptr_size );
|
_Assert( rel_size <= ptr_size );
|
||||||
ptr += rec->size;
|
ptr += rec->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
|
||||||
|
|
||||||
if (rel_size > ptr_size ) {
|
if (rel_size > ptr_size ) {
|
||||||
ret_val = RTEMS_INVALID_NUMBER;
|
ret_val = RTEMS_INVALID_NUMBER;
|
||||||
rel_size = ptr_size;
|
rel_size = ptr_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_count -= count;
|
*total -= count;
|
||||||
|
|
||||||
if (count)
|
if (count) {
|
||||||
rtems_capture_buffer_free( &capture_records, rel_size );
|
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;
|
return ret_val;
|
||||||
}
|
}
|
||||||
@@ -1308,5 +1335,3 @@ rtems_capture_get_control_list (void)
|
|||||||
{
|
{
|
||||||
return capture_controls;
|
return capture_controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -520,9 +520,6 @@ rtems_capture_clear_trigger (rtems_name from_name,
|
|||||||
* @brief Capture read records from capture buffer
|
* @brief Capture read records from capture buffer
|
||||||
*
|
*
|
||||||
* This function reads a number of records from the 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
|
* The function returns the number of record that is has that are
|
||||||
* in a continous block of memory. If the number of available records
|
* 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
|
* rtems_capture_release. Calls this function without a release will
|
||||||
* result in at least the same number of records being released.
|
* result in at least the same number of records being released.
|
||||||
*
|
*
|
||||||
* The 'threshold' parameter is the number of records that must be
|
* @param[in] cpu The cpu number that the records were recorded on
|
||||||
* 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[out] read will contain the number of records read
|
* @param[out] read will contain the number of records read
|
||||||
* @param[out] recs The capture records that are 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.
|
* source of the error.
|
||||||
*/
|
*/
|
||||||
rtems_status_code
|
rtems_status_code
|
||||||
rtems_capture_read (uint32_t threshold,
|
rtems_capture_read (uint32_t cpu,
|
||||||
uint32_t timeout,
|
|
||||||
uint32_t* read,
|
uint32_t* read,
|
||||||
rtems_capture_record_t** recs);
|
rtems_capture_record_t** recs);
|
||||||
|
|
||||||
@@ -572,7 +558,7 @@ rtems_capture_read (uint32_t threshold,
|
|||||||
* source of the error.
|
* source of the error.
|
||||||
*/
|
*/
|
||||||
rtems_status_code
|
rtems_status_code
|
||||||
rtems_capture_release (uint32_t count);
|
rtems_capture_release (uint32_t cpu, uint32_t count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief Capture nano-second time period.
|
* @brief Capture nano-second time period.
|
||||||
|
|||||||
@@ -43,14 +43,19 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
* Global capture flags.
|
* Global capture flags.
|
||||||
*/
|
*/
|
||||||
#define RTEMS_CAPTURE_ON (1U << 0)
|
#define RTEMS_CAPTURE_INIT (1u << 0)
|
||||||
#define RTEMS_CAPTURE_NO_MEMORY (1U << 1)
|
#define RTEMS_CAPTURE_ON (1U << 1)
|
||||||
#define RTEMS_CAPTURE_OVERFLOW (1U << 2)
|
#define RTEMS_CAPTURE_NO_MEMORY (1U << 2)
|
||||||
#define RTEMS_CAPTURE_TRIGGERED (1U << 3)
|
#define RTEMS_CAPTURE_TRIGGERED (1U << 3)
|
||||||
#define RTEMS_CAPTURE_READER_ACTIVE (1U << 4)
|
#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 4)
|
||||||
#define RTEMS_CAPTURE_READER_WAITING (1U << 5)
|
#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 5)
|
||||||
#define RTEMS_CAPTURE_GLOBAL_WATCH (1U << 6)
|
|
||||||
#define RTEMS_CAPTURE_ONLY_MONITOR (1U << 7)
|
/*
|
||||||
|
* 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.
|
* @brief Capture set extension index.
|
||||||
|
|||||||
Reference in New Issue
Block a user