forked from Imagelibrary/rtems
capture: Add support for variable length records.
This commit is contained in:
@@ -149,6 +149,7 @@ include_rtems_HEADERS += libmisc/bspcmdline/bspcmdline.h
|
||||
## capture
|
||||
include_rtems_HEADERS += libmisc/capture/capture.h
|
||||
include_rtems_HEADERS += libmisc/capture/capture-cli.h
|
||||
include_rtems_HEADERS += libmisc/capture/captureimpl.h
|
||||
|
||||
## cpuuse
|
||||
include_rtems_HEADERS += libmisc/cpuuse/cpuuse.h
|
||||
|
||||
@@ -18,8 +18,9 @@ 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.h capture/captureimpl.h capture/capture-cli.h
|
||||
capture/capture_user_extension.c capture/capture_buffer.c \
|
||||
capture/capture.h capture/captureimpl.h capture/capture-cli.h \
|
||||
capture/capture_buffer.h
|
||||
|
||||
## cpuuse
|
||||
EXTRA_DIST += cpuuse/README
|
||||
|
||||
@@ -1353,6 +1353,7 @@ rtems_capture_cli_trace_records (int argc,
|
||||
int count;
|
||||
uint32_t read;
|
||||
rtems_capture_record_t* rec;
|
||||
uint8_t* ptr;
|
||||
int arg;
|
||||
rtems_capture_time_t last_t = 0;
|
||||
|
||||
@@ -1408,9 +1409,11 @@ rtems_capture_cli_trace_records (int argc,
|
||||
}
|
||||
|
||||
count = total < read ? total : read;
|
||||
|
||||
ptr = (uint8_t *) rec;
|
||||
while (count--)
|
||||
{
|
||||
rec = (rtems_capture_record_t*) ptr;
|
||||
|
||||
if (csv)
|
||||
fprintf (stdout, "%08" PRIxPTR ",%03" PRIu32
|
||||
",%03" PRIu32 ",%04" PRIx32 ",%" PRId64 "\n",
|
||||
@@ -1450,7 +1453,7 @@ rtems_capture_cli_trace_records (int argc,
|
||||
event >>= 1;
|
||||
}
|
||||
}
|
||||
rec++;
|
||||
ptr += rec->size;
|
||||
}
|
||||
|
||||
count = total < read ? total : read;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <rtems/rtems/tasksimpl.h>
|
||||
|
||||
#include "captureimpl.h"
|
||||
#include "capture_buffer.h"
|
||||
|
||||
#include <rtems/score/statesimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
@@ -52,7 +53,9 @@
|
||||
RTEMS_CAPTURE_DELETED_EVENT | \
|
||||
RTEMS_CAPTURE_BEGIN_EVENT | \
|
||||
RTEMS_CAPTURE_EXITTED_EVENT | \
|
||||
RTEMS_CAPTURE_TERMINATED_EVENT)
|
||||
RTEMS_CAPTURE_TERMINATED_EVENT | \
|
||||
RTEMS_CAPTURE_AUTOGEN_ENTRY_EVENT | \
|
||||
RTEMS_CAPTURE_AUTOGEN_EXIT_EVENT)
|
||||
#else
|
||||
#define RTEMS_CAPTURE_RECORD_EVENTS (0)
|
||||
#endif
|
||||
@@ -61,11 +64,8 @@
|
||||
/*
|
||||
* RTEMS Capture Data.
|
||||
*/
|
||||
static rtems_capture_record_t* capture_records;
|
||||
static uint32_t capture_size;
|
||||
static rtems_capture_buffer_t capture_records = {NULL, 0, 0, 0, 0, 0};
|
||||
static uint32_t capture_count;
|
||||
static rtems_capture_record_t* capture_in;
|
||||
static uint32_t capture_out;
|
||||
static uint32_t capture_flags;
|
||||
static rtems_capture_task_t* capture_tasks;
|
||||
static rtems_capture_control_t* capture_controls;
|
||||
@@ -464,16 +464,12 @@ rtems_capture_destroy_capture_task (rtems_capture_task_t* task)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function records a capture record into the capture buffer.
|
||||
* This function indicates if data should be filtered from the
|
||||
* log.
|
||||
*/
|
||||
void
|
||||
rtems_capture_record (rtems_capture_task_t* task,
|
||||
uint32_t events)
|
||||
bool rtems_capture_filter( rtems_capture_task_t* task,
|
||||
uint32_t events)
|
||||
{
|
||||
/*
|
||||
* Check the watch state if we have a task control, and
|
||||
* the task's real priority is lower or equal to the ceiling.
|
||||
*/
|
||||
if (task &&
|
||||
((capture_flags &
|
||||
(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
|
||||
@@ -494,35 +490,55 @@ rtems_capture_record (rtems_capture_task_t* task,
|
||||
((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
|
||||
(control && (control->flags & RTEMS_CAPTURE_WATCH)))))
|
||||
{
|
||||
rtems_interrupt_lock_context lock_context;
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
if (capture_count < capture_size)
|
||||
{
|
||||
capture_count++;
|
||||
capture_in->task = task;
|
||||
capture_in->events = (events |
|
||||
(task->tcb->real_priority) |
|
||||
(task->tcb->current_priority << 8));
|
||||
|
||||
if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
|
||||
task->flags |= RTEMS_CAPTURE_TRACED;
|
||||
|
||||
rtems_capture_get_time (&capture_in->time);
|
||||
|
||||
if (capture_in == &capture_records[capture_size - 1])
|
||||
capture_in = capture_records;
|
||||
else
|
||||
capture_in++;
|
||||
|
||||
rtems_capture_refcount_up (task);
|
||||
}
|
||||
else
|
||||
capture_flags |= RTEMS_CAPTURE_OVERFLOW;
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function records a capture record into the capture buffer.
|
||||
*/
|
||||
void *
|
||||
rtems_capture_record_open (rtems_capture_task_t* task,
|
||||
uint32_t events,
|
||||
size_t size,
|
||||
rtems_interrupt_lock_context* lock_context)
|
||||
{
|
||||
uint8_t* ptr;
|
||||
rtems_capture_record_t* capture_in;
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, lock_context);
|
||||
|
||||
ptr = rtems_capture_buffer_allocate(&capture_records, size);
|
||||
capture_in = (rtems_capture_record_t *) ptr;
|
||||
if ( capture_in )
|
||||
{
|
||||
capture_count++;
|
||||
capture_in->size = size;
|
||||
capture_in->task = task;
|
||||
capture_in->events = (events |
|
||||
(task->tcb->real_priority) |
|
||||
(task->tcb->current_priority << 8));
|
||||
|
||||
if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
|
||||
task->flags |= RTEMS_CAPTURE_TRACED;
|
||||
|
||||
rtems_capture_get_time (&capture_in->time);
|
||||
|
||||
rtems_capture_refcount_up (task);
|
||||
ptr = ptr + sizeof(*capture_in);
|
||||
}
|
||||
else
|
||||
capture_flags |= 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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -607,18 +623,15 @@ rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribu
|
||||
* See if the capture engine is already open.
|
||||
*/
|
||||
|
||||
if (capture_records)
|
||||
if (capture_records.buffer)
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
|
||||
capture_records = malloc (size * sizeof (rtems_capture_record_t));
|
||||
rtems_capture_buffer_create( &capture_records, size );
|
||||
|
||||
if (capture_records == NULL)
|
||||
if (capture_records.buffer == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
|
||||
capture_size = size;
|
||||
capture_count = 0;
|
||||
capture_in = capture_records;
|
||||
capture_out = 0;
|
||||
capture_flags = 0;
|
||||
capture_tasks = NULL;
|
||||
capture_ceiling = 0;
|
||||
@@ -628,8 +641,7 @@ rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribu
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
free (capture_records);
|
||||
capture_records = NULL;
|
||||
rtems_capture_buffer_destroy( &capture_records);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -653,7 +665,7 @@ rtems_capture_close (void)
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
if (!capture_records)
|
||||
if (!capture_records.buffer)
|
||||
{
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -661,8 +673,6 @@ rtems_capture_close (void)
|
||||
|
||||
capture_flags &= ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR);
|
||||
|
||||
capture_records = NULL;
|
||||
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
|
||||
/*
|
||||
@@ -697,10 +707,9 @@ rtems_capture_close (void)
|
||||
|
||||
capture_controls = NULL;
|
||||
|
||||
if (capture_records)
|
||||
if (capture_records.buffer)
|
||||
{
|
||||
free (capture_records);
|
||||
capture_records = NULL;
|
||||
rtems_capture_buffer_destroy( &capture_records);
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -722,7 +731,7 @@ rtems_capture_control (bool enable)
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
if (!capture_records)
|
||||
if (!capture_records.buffer)
|
||||
{
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
return RTEMS_UNSATISFIED;
|
||||
@@ -752,7 +761,7 @@ rtems_capture_monitor (bool enable)
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
if (!capture_records)
|
||||
if (!capture_records.buffer)
|
||||
{
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
return RTEMS_UNSATISFIED;
|
||||
@@ -791,9 +800,8 @@ rtems_capture_flush (bool prime)
|
||||
else
|
||||
capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
|
||||
|
||||
rtems_capture_buffer_flush( &capture_records );
|
||||
capture_count = 0;
|
||||
capture_in = capture_records;
|
||||
capture_out = 0;
|
||||
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
|
||||
@@ -1195,6 +1203,26 @@ rtems_capture_clear_trigger (rtems_name from_name,
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1229,7 +1257,8 @@ rtems_capture_read (uint32_t threshold,
|
||||
{
|
||||
rtems_interrupt_lock_context lock_context;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
uint32_t count;
|
||||
size_t recs_size = 0;
|
||||
bool wrapped;
|
||||
|
||||
*read = 0;
|
||||
*recs = NULL;
|
||||
@@ -1247,25 +1276,24 @@ rtems_capture_read (uint32_t threshold,
|
||||
}
|
||||
|
||||
capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
|
||||
*read = count = capture_count;
|
||||
|
||||
*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);
|
||||
|
||||
*recs = &capture_records[capture_out];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* See if the count wraps the end of the record buffer.
|
||||
* See if the data wraps the end of the record buffer.
|
||||
*/
|
||||
if (count && ((capture_out + count) >= capture_size))
|
||||
*read = capture_size - capture_out;
|
||||
wrapped = rtems_capture_buffer_has_wrapped( &capture_records);
|
||||
|
||||
/*
|
||||
* Do we have a threshold and the current count has not wrapped
|
||||
* Do we have a threshold and have not wrapped
|
||||
* around the end of the capture record buffer ?
|
||||
*/
|
||||
if ((*read == count) && threshold)
|
||||
if ((!wrapped) && threshold)
|
||||
{
|
||||
/*
|
||||
* Do we have enough records ?
|
||||
@@ -1297,7 +1325,8 @@ rtems_capture_read (uint32_t threshold,
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
*read = count = capture_count;
|
||||
*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);
|
||||
|
||||
@@ -1322,8 +1351,10 @@ rtems_status_code
|
||||
rtems_capture_release (uint32_t count)
|
||||
{
|
||||
rtems_interrupt_lock_context lock_context;
|
||||
uint8_t* ptr;
|
||||
rtems_capture_record_t* rec;
|
||||
uint32_t counted;
|
||||
size_t ptr_size = 0;
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
@@ -1333,21 +1364,26 @@ rtems_capture_release (uint32_t count)
|
||||
rtems_interrupt_lock_release (&capture_lock, &lock_context);
|
||||
|
||||
counted = count;
|
||||
|
||||
ptr = rtems_capture_buffer_peek( &capture_records, &ptr_size );
|
||||
_Assert(ptr_size >= (count * sizeof(*rec) ));
|
||||
|
||||
rec = &capture_records[capture_out];
|
||||
|
||||
ptr_size = 0;
|
||||
while (counted--)
|
||||
{
|
||||
{
|
||||
rec = (rtems_capture_record_t*) ptr;
|
||||
ptr_size += rec->size;
|
||||
rtems_capture_refcount_down (rec->task);
|
||||
rtems_capture_destroy_capture_task (rec->task);
|
||||
rec++;
|
||||
ptr += rec->size;
|
||||
}
|
||||
|
||||
rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
|
||||
|
||||
capture_count -= count;
|
||||
|
||||
capture_out = (capture_out + count) % capture_size;
|
||||
if (count)
|
||||
rtems_capture_buffer_free( &capture_records, ptr_size );
|
||||
|
||||
capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
|
||||
|
||||
@@ -1430,3 +1466,5 @@ rtems_capture_get_control_list (void)
|
||||
{
|
||||
return capture_controls;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@ typedef struct rtems_capture_record_s
|
||||
rtems_capture_task_t* task;
|
||||
uint32_t events;
|
||||
rtems_capture_time_t time;
|
||||
size_t size;
|
||||
} rtems_capture_record_t;
|
||||
|
||||
/**
|
||||
|
||||
117
cpukit/libmisc/capture/capture_buffer.c
Normal file
117
cpukit/libmisc/capture/capture_buffer.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
|
||||
COPYRIGHT (c) 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 the Target Interface Command Line Interface. You need
|
||||
start the RTEMS monitor.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/score/assert.h>
|
||||
#include "capture_buffer.h"
|
||||
|
||||
void * rtems_capture_buffer_allocate( rtems_capture_buffer_t* buffer, size_t size )
|
||||
{
|
||||
static uint32_t end;
|
||||
static void *ptr;
|
||||
|
||||
if ( rtems_capture_buffer_is_full( buffer ) )
|
||||
return NULL;
|
||||
|
||||
if ( (buffer->count + size) > buffer->end )
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Determine if the end of free space is marked with
|
||||
* the end of buffer space, or the head of allocated
|
||||
* space.
|
||||
*
|
||||
* |...|head| freespace |tail| ...| end
|
||||
*
|
||||
* tail|.....|head| freespace| end
|
||||
*
|
||||
*/
|
||||
if (buffer->tail > buffer->head) {
|
||||
end = buffer->tail;
|
||||
} else {
|
||||
end = buffer->end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Can we allocate it easily?
|
||||
*/
|
||||
if ((buffer->head + size) <= end) {
|
||||
ptr = &buffer->buffer[ buffer->head ];
|
||||
buffer->head += size;
|
||||
buffer->count = buffer->count + size;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to consider wrapping around to the front of the buffer
|
||||
*/
|
||||
|
||||
/* If there is not room at the end of the buffer */
|
||||
/* and we have we already wrapped then we can't allocate */
|
||||
if ( end == buffer->tail )
|
||||
return NULL;
|
||||
|
||||
/* Is there no room at the front of the buffer */
|
||||
if ( (buffer->tail < size ))
|
||||
return NULL;
|
||||
|
||||
/* change the end pointer to the last used byte, so a read will wrap when out of data */
|
||||
buffer->end = buffer->head;
|
||||
|
||||
/* now return the buffer */
|
||||
ptr = buffer->buffer;
|
||||
buffer->head = size;
|
||||
buffer->count = buffer->count + size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *rtems_capture_buffer_free( rtems_capture_buffer_t* buffer, size_t size )
|
||||
{
|
||||
static void *ptr;
|
||||
static uint32_t next;
|
||||
size_t buff_size;
|
||||
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
|
||||
ptr = rtems_capture_buffer_peek(buffer, &buff_size);
|
||||
next = buffer->tail + size;
|
||||
|
||||
/* Check if we are freeing space past the end of the buffer */
|
||||
_Assert( ! rtems_capture_buffer_is_empty( buffer ) );
|
||||
_Assert( !((buffer->tail > buffer->head) && (next > buffer->end)) );
|
||||
_Assert( !((buffer->tail < buffer->head) && (next > buffer->head)) );
|
||||
|
||||
buffer->count = buffer->count - size;
|
||||
|
||||
if (next == buffer->end) {
|
||||
buffer->end = buffer->size;
|
||||
buffer->tail = 0;
|
||||
} else {
|
||||
buffer->tail = next;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
105
cpukit/libmisc/capture/capture_buffer.h
Normal file
105
cpukit/libmisc/capture/capture_buffer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file capture_buffer.h
|
||||
*
|
||||
* @brief Capture buffer
|
||||
*
|
||||
* This is a set of functions to control a variable length capture record buffer.
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
|
||||
COPYRIGHT (c) 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.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __CAPTUREBUFFER_H_
|
||||
#define __CAPTUREBUFFER_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/**@{*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
size_t size;
|
||||
volatile uint32_t count;
|
||||
volatile uint32_t head;
|
||||
volatile uint32_t tail;
|
||||
volatile uint32_t end;
|
||||
} rtems_capture_buffer_t;
|
||||
|
||||
static inline void rtems_capture_buffer_flush( rtems_capture_buffer_t* buffer )
|
||||
{
|
||||
buffer->end = buffer->size;
|
||||
buffer->head = buffer->tail = 0;
|
||||
buffer->count = 0;
|
||||
}
|
||||
|
||||
static inline void rtems_capture_buffer_create( rtems_capture_buffer_t* buffer, size_t size )
|
||||
{
|
||||
buffer->buffer = malloc(size);
|
||||
buffer->size = size;
|
||||
rtems_capture_buffer_flush( buffer );
|
||||
}
|
||||
|
||||
static inline void rtems_capture_buffer_destroy( rtems_capture_buffer_t* buffer )
|
||||
{
|
||||
rtems_capture_buffer_flush( buffer );
|
||||
free( buffer->buffer);
|
||||
buffer->buffer = NULL;
|
||||
}
|
||||
|
||||
static inline bool rtems_capture_buffer_is_empty( rtems_capture_buffer_t* buffer )
|
||||
{
|
||||
return( buffer->count == 0 );
|
||||
}
|
||||
|
||||
static inline bool rtems_capture_buffer_is_full( rtems_capture_buffer_t* buffer )
|
||||
{
|
||||
return (buffer->count == buffer->size);
|
||||
}
|
||||
|
||||
static inline bool rtems_capture_buffer_has_wrapped( rtems_capture_buffer_t* buffer )
|
||||
{
|
||||
if ( buffer->tail > buffer->head)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void *rtems_capture_buffer_peek( rtems_capture_buffer_t* buffer, size_t *size )
|
||||
{
|
||||
if (rtems_capture_buffer_is_empty(buffer)) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( buffer->tail > buffer->head)
|
||||
*size = buffer->end - buffer->tail;
|
||||
else
|
||||
*size = buffer->head - buffer->tail;
|
||||
|
||||
return &buffer->buffer[ buffer->tail ];
|
||||
}
|
||||
|
||||
void *rtems_capture_buffer_allocate( rtems_capture_buffer_t* buffer, size_t size );
|
||||
|
||||
void *rtems_capture_buffer_free( rtems_capture_buffer_t* buffer, size_t size );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -84,6 +84,23 @@ static const rtems_extensions_table capture_extensions = {
|
||||
.thread_terminate = rtems_capture_terminated_task
|
||||
};
|
||||
|
||||
|
||||
static inline void rtems_capture_record (
|
||||
rtems_capture_task_t* task,
|
||||
uint32_t events
|
||||
)
|
||||
{
|
||||
rtems_capture_record_t* rec;
|
||||
|
||||
if (rtems_capture_filter( task, events) )
|
||||
return;
|
||||
|
||||
rtems_capture_begin_add_record (task, events, sizeof(*rec), &rec);
|
||||
|
||||
rtems_capture_end_add_record ( rec );
|
||||
}
|
||||
|
||||
|
||||
rtems_status_code rtems_capture_user_extension_open(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
@@ -154,6 +154,89 @@ rtems_capture_task_t* rtems_capture_create_capture_task (rtems_tcb* new_task);
|
||||
bool rtems_capture_trigger (rtems_capture_task_t* ft,
|
||||
rtems_capture_task_t* tt,
|
||||
uint32_t events);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* rtems_capture_end_add_record.
|
||||
*
|
||||
* @param[in] rec specifies the next location to write in the record
|
||||
* @param[in] data specifies the data to write
|
||||
* @param[in] size specifies specifies the size of the data
|
||||
*
|
||||
* @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
|
||||
* rtems_capture_end_add_record.
|
||||
*/
|
||||
static void *rtems_capture_append_to_record(void* rec,
|
||||
void* data,
|
||||
size_t size );
|
||||
|
||||
/**
|
||||
* @brief Capture filter
|
||||
*
|
||||
* This function this function specifies if the given task
|
||||
* and events should be logged.
|
||||
*
|
||||
* @param[in] task specifies the capture task control block
|
||||
* @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
|
||||
* should be logged.
|
||||
*/
|
||||
bool rtems_capture_filter( rtems_capture_task_t* task,
|
||||
uint32_t events);
|
||||
/**
|
||||
* @brief Capture begin add record.
|
||||
*
|
||||
* This function opens a record for writing and inserts
|
||||
* the header information
|
||||
*
|
||||
* @param[in] _task specifies the capture task block
|
||||
* @param[in] _events specifies the events
|
||||
* @param[in] _size specifies the expected size of the capture record
|
||||
* @param[out] _rec specifies the next write point in the capture record
|
||||
*/
|
||||
#define rtems_capture_begin_add_record( _task, _events, _size, _rec) \
|
||||
do { \
|
||||
rtems_interrupt_lock_context _lock_context; \
|
||||
*_rec = rtems_capture_record_open( _task, _events, _size, &_lock_context );
|
||||
|
||||
/**
|
||||
* @brief Capture append to record.
|
||||
*
|
||||
* 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] 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,
|
||||
void* data,
|
||||
size_t size )
|
||||
{
|
||||
uint8_t *ptr = rec;
|
||||
memcpy( ptr, data, size );
|
||||
return (ptr + size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Capture end add record.
|
||||
*
|
||||
* This function completes the add capture record process
|
||||
*
|
||||
* @param[in] _rec specifies the end of the capture record
|
||||
*/
|
||||
#define rtems_capture_end_add_record( _rec ) \
|
||||
rtems_capture_record_close( _rec, &_lock_context ); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Capture initialize stack usage
|
||||
*
|
||||
@@ -187,6 +270,39 @@ void rtems_capture_destroy_capture_task (rtems_capture_task_t* task);
|
||||
*/
|
||||
void rtems_capture_get_time (rtems_capture_time_t* time);
|
||||
|
||||
/**
|
||||
* @brief Capture record open.
|
||||
*
|
||||
* This function allocates a record and fills in the
|
||||
* header information. It does a lock acquire
|
||||
* which will remain in effect until
|
||||
* rtems_capture_record_close is called. This method
|
||||
* should only be used by rtems_capture_begin_add_record.
|
||||
*
|
||||
* @param[in] task specifies the caputre task block
|
||||
* @param[in] events specifies the events
|
||||
* @param[in] size specifies capture record size
|
||||
* @param[out] lock_context specifies the lock context
|
||||
*
|
||||
* @retval This method returns a pointer to the next location in
|
||||
* the capture record to store data.
|
||||
*/
|
||||
void* rtems_capture_record_open (rtems_capture_task_t* task,
|
||||
uint32_t events,
|
||||
size_t size,
|
||||
rtems_interrupt_lock_context* lock_context);
|
||||
/**
|
||||
* @brief Capture record close.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param[in] rec specifies the record
|
||||
* @param[out] lock_context specifies the lock context
|
||||
*/
|
||||
void rtems_capture_record_close( void *rec, rtems_interrupt_lock_context* lock_context);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -330,6 +330,10 @@ $(PROJECT_INCLUDE)/rtems/capture-cli.h: libmisc/capture/capture-cli.h $(PROJECT_
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/capture-cli.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/capture-cli.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/captureimpl.h: libmisc/capture/captureimpl.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/captureimpl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/captureimpl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/cpuuse.h: libmisc/cpuuse/cpuuse.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/cpuuse.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/cpuuse.h
|
||||
|
||||
Reference in New Issue
Block a user