summaryrefslogtreecommitdiffstats
path: root/cpukit/libmisc/capture
diff options
context:
space:
mode:
authorJennifer Averett <jennifer.averett@oarcorp.com>2014-08-05 15:48:01 -0500
committerJennifer Averett <jennifer.averett@oarcorp.com>2014-09-05 06:50:29 -0500
commit2a86615b98ee22eb2cb664011f97ae3a4d07e294 (patch)
tree85efc211e857475d43746da23492b2500f9415f6 /cpukit/libmisc/capture
parentcapture: Split user extension methods out. (diff)
downloadrtems-2a86615b98ee22eb2cb664011f97ae3a4d07e294.tar.bz2
capture: Add support for variable length records.
Diffstat (limited to 'cpukit/libmisc/capture')
-rw-r--r--cpukit/libmisc/capture/capture-cli.c7
-rw-r--r--cpukit/libmisc/capture/capture.c174
-rw-r--r--cpukit/libmisc/capture/capture.h1
-rw-r--r--cpukit/libmisc/capture/capture_buffer.c117
-rw-r--r--cpukit/libmisc/capture/capture_buffer.h105
-rw-r--r--cpukit/libmisc/capture/capture_user_extension.c17
-rw-r--r--cpukit/libmisc/capture/captureimpl.h116
7 files changed, 467 insertions, 70 deletions
diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c
index 9c978d28d9..2aa7c9c229 100644
--- a/cpukit/libmisc/capture/capture-cli.c
+++ b/cpukit/libmisc/capture/capture-cli.c
@@ -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;
diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c
index 54b289439b..64d2699f88 100644
--- a/cpukit/libmisc/capture/capture.c
+++ b/cpukit/libmisc/capture/capture.c
@@ -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;
+ return false;
+ }
+ }
- rtems_interrupt_lock_acquire (&capture_lock, &lock_context);
+ return true;
+}
- if (capture_count < capture_size)
- {
- capture_count++;
- capture_in->task = task;
- capture_in->events = (events |
- (task->tcb->real_priority) |
- (task->tcb->current_priority << 8));
+/*
+ * 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;
- if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
- task->flags |= RTEMS_CAPTURE_TRACED;
+ rtems_interrupt_lock_acquire (&capture_lock, lock_context);
- rtems_capture_get_time (&capture_in->time);
+ 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 (capture_in == &capture_records[capture_size - 1])
- capture_in = capture_records;
- else
- capture_in++;
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
+ task->flags |= RTEMS_CAPTURE_TRACED;
- rtems_capture_refcount_up (task);
- }
- else
- capture_flags |= RTEMS_CAPTURE_OVERFLOW;
- rtems_interrupt_lock_release (&capture_lock, &lock_context);
- }
+ 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;
- rtems_interrupt_lock_release (&capture_lock, &lock_context);
+ *recs = rtems_capture_buffer_peek( &capture_records, &recs_size );
+ *read = rtems_capture_count_records( *recs, recs_size );
- *recs = &capture_records[capture_out];
+ rtems_interrupt_lock_release (&capture_lock, &lock_context);
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;
}
+
+
diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
index 737c73f754..8bc2fc3f3b 100644
--- a/cpukit/libmisc/capture/capture.h
+++ b/cpukit/libmisc/capture/capture.h
@@ -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;
/**
diff --git a/cpukit/libmisc/capture/capture_buffer.c b/cpukit/libmisc/capture/capture_buffer.c
new file mode 100644
index 0000000000..9557f70ba8
--- /dev/null
+++ b/cpukit/libmisc/capture/capture_buffer.c
@@ -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;
+}
diff --git a/cpukit/libmisc/capture/capture_buffer.h b/cpukit/libmisc/capture/capture_buffer.h
new file mode 100644
index 0000000000..a01ca29654
--- /dev/null
+++ b/cpukit/libmisc/capture/capture_buffer.h
@@ -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
diff --git a/cpukit/libmisc/capture/capture_user_extension.c b/cpukit/libmisc/capture/capture_user_extension.c
index f3bebc829a..4236d8caeb 100644
--- a/cpukit/libmisc/capture/capture_user_extension.c
+++ b/cpukit/libmisc/capture/capture_user_extension.c
@@ -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;
diff --git a/cpukit/libmisc/capture/captureimpl.h b/cpukit/libmisc/capture/captureimpl.h
index ee18d827ad..fa366889b7 100644
--- a/cpukit/libmisc/capture/captureimpl.h
+++ b/cpukit/libmisc/capture/captureimpl.h
@@ -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
}