forked from Imagelibrary/rtems
capture: Split user extension methods out.
This commit is contained in:
@@ -18,7 +18,8 @@ EXTRA_DIST += capture/README
|
||||
|
||||
noinst_LIBRARIES += libcapture.a
|
||||
libcapture_a_SOURCES = capture/capture.c capture/capture-cli.c \
|
||||
capture/capture.h capture/capture-cli.h
|
||||
capture/capture_user_extension.c \
|
||||
capture/capture.h capture/captureimpl.h capture/capture-cli.h
|
||||
|
||||
## cpuuse
|
||||
EXTRA_DIST += cpuuse/README
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <rtems/rtems/tasksimpl.h>
|
||||
|
||||
#include "capture.h"
|
||||
#include "captureimpl.h"
|
||||
|
||||
#include <rtems/score/statesimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
@@ -57,46 +57,6 @@
|
||||
#define RTEMS_CAPTURE_RECORD_EVENTS (0)
|
||||
#endif
|
||||
|
||||
static bool
|
||||
rtems_capture_create_task (rtems_tcb* current_task,
|
||||
rtems_tcb* new_task);
|
||||
|
||||
static void
|
||||
rtems_capture_start_task (rtems_tcb* current_task,
|
||||
rtems_tcb* started_task);
|
||||
|
||||
static void
|
||||
rtems_capture_restart_task (rtems_tcb* current_task,
|
||||
rtems_tcb* restarted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_delete_task (rtems_tcb* current_task,
|
||||
rtems_tcb* deleted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_tcb* heir_task);
|
||||
|
||||
static void
|
||||
rtems_capture_begin_task (rtems_tcb* begin_task);
|
||||
|
||||
static void
|
||||
rtems_capture_exitted_task (rtems_tcb* exitted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_terminated_task (rtems_tcb* terminated_task);
|
||||
|
||||
/*
|
||||
* 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_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)
|
||||
|
||||
/*
|
||||
* RTEMS Capture Data.
|
||||
@@ -110,7 +70,6 @@ static uint32_t capture_flags;
|
||||
static rtems_capture_task_t* capture_tasks;
|
||||
static rtems_capture_control_t* capture_controls;
|
||||
static int capture_extension_index;
|
||||
static rtems_id capture_id;
|
||||
static rtems_capture_timestamp capture_timestamp;
|
||||
static rtems_task_priority capture_ceiling;
|
||||
static rtems_task_priority capture_floor;
|
||||
@@ -118,18 +77,6 @@ static rtems_id capture_reader;
|
||||
static rtems_interrupt_lock capture_lock =
|
||||
RTEMS_INTERRUPT_LOCK_INITIALIZER("capture");
|
||||
|
||||
static const rtems_extensions_table capture_extensions = {
|
||||
.thread_create = rtems_capture_create_task,
|
||||
.thread_start = rtems_capture_start_task,
|
||||
.thread_restart = rtems_capture_restart_task,
|
||||
.thread_delete = rtems_capture_delete_task,
|
||||
.thread_switch = rtems_capture_switch_task,
|
||||
.thread_begin = rtems_capture_begin_task,
|
||||
.thread_exitted = rtems_capture_exitted_task,
|
||||
.fatal = NULL,
|
||||
.thread_terminate = rtems_capture_terminated_task
|
||||
};
|
||||
|
||||
/*
|
||||
* RTEMS Event text.
|
||||
*/
|
||||
@@ -151,11 +98,43 @@ static const char* capture_event_text[] =
|
||||
"TIMESTAMP"
|
||||
};
|
||||
|
||||
void rtems_capture_set_extension_index(int index)
|
||||
{
|
||||
capture_extension_index = index;
|
||||
}
|
||||
|
||||
int rtems_capture_get_extension_index(void)
|
||||
{
|
||||
return capture_extension_index;
|
||||
}
|
||||
|
||||
uint32_t rtems_capture_get_flags(void)
|
||||
{
|
||||
return capture_flags;
|
||||
}
|
||||
|
||||
void rtems_capture_set_flags(uint32_t mask)
|
||||
{
|
||||
capture_flags |= mask;
|
||||
}
|
||||
|
||||
|
||||
rtems_capture_task_t* rtems_capture_find_capture_task( rtems_id ct_id )
|
||||
{
|
||||
rtems_capture_task_t* ct;
|
||||
|
||||
for (ct = capture_tasks; ct; ct = ct->forw) {
|
||||
if (ct->id == ct_id)
|
||||
break;
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the current time. If a handler is provided
|
||||
* by the user get the time from that.
|
||||
*/
|
||||
static inline void
|
||||
void
|
||||
rtems_capture_get_time (rtems_capture_time_t* time)
|
||||
{
|
||||
if (capture_timestamp)
|
||||
@@ -290,7 +269,7 @@ rtems_capture_refcount_down (rtems_capture_task_t* task)
|
||||
/*
|
||||
* This function setups a stack so its usage can be monitored.
|
||||
*/
|
||||
static inline void
|
||||
void
|
||||
rtems_capture_init_stack_usage (rtems_capture_task_t* task)
|
||||
{
|
||||
if (task->tcb)
|
||||
@@ -378,7 +357,7 @@ rtems_capture_create_control (rtems_name name, rtems_id id)
|
||||
/*
|
||||
* This function create the task control.
|
||||
*/
|
||||
static inline rtems_capture_task_t*
|
||||
rtems_capture_task_t*
|
||||
rtems_capture_create_capture_task (rtems_tcb* new_task)
|
||||
{
|
||||
rtems_interrupt_lock_context lock_context;
|
||||
@@ -456,7 +435,7 @@ rtems_capture_create_capture_task (rtems_tcb* new_task)
|
||||
* is 0 and the tcb has been cleared signalling the task has been
|
||||
* deleted.
|
||||
*/
|
||||
static inline void
|
||||
void
|
||||
rtems_capture_destroy_capture_task (rtems_capture_task_t* task)
|
||||
{
|
||||
if (task)
|
||||
@@ -487,7 +466,7 @@ rtems_capture_destroy_capture_task (rtems_capture_task_t* task)
|
||||
/*
|
||||
* This function records a capture record into the capture buffer.
|
||||
*/
|
||||
static inline void
|
||||
void
|
||||
rtems_capture_record (rtems_capture_task_t* task,
|
||||
uint32_t events)
|
||||
{
|
||||
@@ -550,7 +529,7 @@ rtems_capture_record (rtems_capture_task_t* task,
|
||||
* See if we have triggered and if not see if this event is a
|
||||
* cause of a trigger.
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
rtems_capture_trigger (rtems_capture_task_t* ft,
|
||||
rtems_capture_task_t* tt,
|
||||
uint32_t events)
|
||||
@@ -615,321 +594,6 @@ rtems_capture_trigger (rtems_capture_task_t* ft,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is created.
|
||||
*/
|
||||
static bool
|
||||
rtems_capture_create_task (rtems_tcb* current_task,
|
||||
rtems_tcb* new_task)
|
||||
{
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* nt;
|
||||
|
||||
ct = current_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
/*
|
||||
* Create the new task's capture control block.
|
||||
*/
|
||||
nt = rtems_capture_create_capture_task (new_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, nt, RTEMS_CAPTURE_CREATE))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
|
||||
rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
|
||||
}
|
||||
|
||||
return 1 == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is started.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_start_task (rtems_tcb* current_task,
|
||||
rtems_tcb* started_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* st;
|
||||
|
||||
ct = current_task->extensions[capture_extension_index];
|
||||
st = started_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (st == NULL)
|
||||
st = rtems_capture_create_capture_task (started_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, st, RTEMS_CAPTURE_START))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
|
||||
rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_init_stack_usage (st);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is restarted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_restart_task (rtems_tcb* current_task,
|
||||
rtems_tcb* restarted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* rt;
|
||||
|
||||
ct = current_task->extensions[capture_extension_index];
|
||||
rt = restarted_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (rt == NULL)
|
||||
rt = rtems_capture_create_capture_task (restarted_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, rt, RTEMS_CAPTURE_RESTART))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
|
||||
rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_task_stack_usage (rt);
|
||||
rtems_capture_init_stack_usage (rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is deleted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_delete_task (rtems_tcb* current_task,
|
||||
rtems_tcb* deleted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* dt;
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
ct = current_task->extensions[capture_extension_index];
|
||||
dt = deleted_task->extensions[capture_extension_index];
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (dt == NULL)
|
||||
dt = rtems_capture_create_capture_task (deleted_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, dt, RTEMS_CAPTURE_DELETE))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
|
||||
rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_task_stack_usage (dt);
|
||||
|
||||
/*
|
||||
* This task's tcb will be invalid. This signals the
|
||||
* task has been deleted.
|
||||
*/
|
||||
dt->tcb = 0;
|
||||
|
||||
rtems_capture_destroy_capture_task (dt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is begun.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_begin_task (rtems_tcb* begin_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* bt;
|
||||
|
||||
bt = begin_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (bt == NULL)
|
||||
bt = rtems_capture_create_capture_task (begin_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, bt, RTEMS_CAPTURE_BEGIN))
|
||||
rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is exitted. That is
|
||||
* returned rather than was deleted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_exitted_task (rtems_tcb* exitted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* et;
|
||||
|
||||
et = exitted_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (et == NULL)
|
||||
et = rtems_capture_create_capture_task (exitted_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, et, RTEMS_CAPTURE_EXITTED))
|
||||
rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
|
||||
|
||||
rtems_capture_task_stack_usage (et);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a termination request is identified.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_terminated_task (rtems_tcb* terminated_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* tt;
|
||||
|
||||
tt = terminated_task->extensions[capture_extension_index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (tt == NULL)
|
||||
tt = rtems_capture_create_capture_task (terminated_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, tt, RTEMS_CAPTURE_TERMINATED))
|
||||
rtems_capture_record (tt, RTEMS_CAPTURE_TERMINATED_EVENT);
|
||||
|
||||
rtems_capture_task_stack_usage (tt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a context is switched.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_tcb* heir_task)
|
||||
{
|
||||
/*
|
||||
* Only perform context switch trace processing if tracing is
|
||||
* enabled.
|
||||
*/
|
||||
if (capture_flags & RTEMS_CAPTURE_ON)
|
||||
{
|
||||
rtems_capture_time_t time;
|
||||
|
||||
/*
|
||||
* Get the cpature task control block so we can update the
|
||||
* reference and perform any watch or trigger functions.
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* ht;
|
||||
|
||||
|
||||
if (_States_Is_dormant (current_task->current_state))
|
||||
{
|
||||
rtems_id ct_id = current_task->Object.id;
|
||||
|
||||
for (ct = capture_tasks; ct; ct = ct->forw)
|
||||
if (ct->id == ct_id)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ct = current_task->extensions[capture_extension_index];
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
}
|
||||
|
||||
ht = heir_task->extensions[capture_extension_index];
|
||||
|
||||
if (ht == NULL)
|
||||
ht = rtems_capture_create_capture_task (heir_task);
|
||||
|
||||
/*
|
||||
* Update the execution time. Assume the time will not overflow
|
||||
* for now. This may need to change.
|
||||
*/
|
||||
rtems_capture_get_time (&time);
|
||||
|
||||
/*
|
||||
* We could end up with null pointers for both the current task
|
||||
* and the heir task.
|
||||
*/
|
||||
|
||||
if (ht)
|
||||
{
|
||||
ht->in++;
|
||||
ht->time_in = time;
|
||||
}
|
||||
|
||||
if (ct)
|
||||
{
|
||||
ct->out++;
|
||||
if (ct->time_in)
|
||||
ct->time += time - ct->time_in;
|
||||
}
|
||||
|
||||
if (rtems_capture_trigger (ct, ht, RTEMS_CAPTURE_SWITCH))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
|
||||
rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function initialises the realtime capture engine allocating the trace
|
||||
* buffer. It is assumed we have a working heap at stage of initialisation.
|
||||
@@ -937,7 +601,6 @@ rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_status_code
|
||||
rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribute__((unused)))
|
||||
{
|
||||
rtems_name name;
|
||||
rtems_status_code sc;
|
||||
|
||||
/*
|
||||
@@ -961,22 +624,13 @@ rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp __attribu
|
||||
capture_ceiling = 0;
|
||||
capture_floor = 255;
|
||||
|
||||
/*
|
||||
* Register the user extension handlers for the CAPture Engine.
|
||||
*/
|
||||
name = rtems_build_name ('C', 'A', 'P', 'E');
|
||||
sc = rtems_extension_create (name, &capture_extensions, &capture_id);
|
||||
sc = rtems_capture_user_extension_open();
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
capture_id = 0;
|
||||
free (capture_records);
|
||||
capture_records = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
capture_extension_index = rtems_object_id_get_index (capture_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the list of existing tasks.
|
||||
@@ -1016,7 +670,7 @@ rtems_capture_close (void)
|
||||
* release the resources we have without them being used.
|
||||
*/
|
||||
|
||||
sc = rtems_extension_delete (capture_id);
|
||||
sc = rtems_capture_user_extension_close();
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
return sc;
|
||||
|
||||
435
cpukit/libmisc/capture/capture_user_extension.c
Normal file
435
cpukit/libmisc/capture/capture_user_extension.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Copyright Objective Design Systems Pty Ltd, 2002
|
||||
All rights reserved Objective Design Systems Pty Ltd, 2002
|
||||
Chris Johns (ccj@acm.org)
|
||||
|
||||
COPYRIGHT (c) 1989-2009.
|
||||
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 Capture Engine component.
|
||||
rtems_status_code rtems_capture_user_extension_open(void);
|
||||
rtems_status_code rtems_capture_user_extension_close(void);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rtems/rtems/tasksimpl.h>
|
||||
|
||||
#include "captureimpl.h"
|
||||
|
||||
#include <rtems/score/statesimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
|
||||
/*
|
||||
* RTEMS Capture User Extension Data.
|
||||
*/
|
||||
static rtems_id capture_id;
|
||||
|
||||
static bool
|
||||
rtems_capture_create_task (rtems_tcb* current_task,
|
||||
rtems_tcb* new_task);
|
||||
|
||||
static void
|
||||
rtems_capture_start_task (rtems_tcb* current_task,
|
||||
rtems_tcb* started_task);
|
||||
|
||||
static void
|
||||
rtems_capture_restart_task (rtems_tcb* current_task,
|
||||
rtems_tcb* restarted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_delete_task (rtems_tcb* current_task,
|
||||
rtems_tcb* deleted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_tcb* heir_task);
|
||||
|
||||
static void
|
||||
rtems_capture_begin_task (rtems_tcb* begin_task);
|
||||
|
||||
static void
|
||||
rtems_capture_exitted_task (rtems_tcb* exitted_task);
|
||||
|
||||
static void
|
||||
rtems_capture_terminated_task (rtems_tcb* terminated_task);
|
||||
|
||||
static const rtems_extensions_table capture_extensions = {
|
||||
.thread_create = rtems_capture_create_task,
|
||||
.thread_start = rtems_capture_start_task,
|
||||
.thread_restart = rtems_capture_restart_task,
|
||||
.thread_delete = rtems_capture_delete_task,
|
||||
.thread_switch = rtems_capture_switch_task,
|
||||
.thread_begin = rtems_capture_begin_task,
|
||||
.thread_exitted = rtems_capture_exitted_task,
|
||||
.fatal = NULL,
|
||||
.thread_terminate = rtems_capture_terminated_task
|
||||
};
|
||||
|
||||
rtems_status_code rtems_capture_user_extension_open(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_name name;
|
||||
int index;
|
||||
|
||||
/*
|
||||
* Register the user extension handlers for the CAPture Engine.
|
||||
*/
|
||||
name = rtems_build_name ('C', 'A', 'P', 'E');
|
||||
sc = rtems_extension_create (name, &capture_extensions, &capture_id);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
capture_id = 0;
|
||||
else {
|
||||
index = rtems_object_id_get_index (capture_id);
|
||||
rtems_capture_set_extension_index( index );
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
rtems_status_code rtems_capture_user_extension_close(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
sc = rtems_extension_delete (capture_id);
|
||||
return sc;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is created.
|
||||
*/
|
||||
static bool
|
||||
rtems_capture_create_task (rtems_tcb* current_task,
|
||||
rtems_tcb* new_task)
|
||||
{
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* nt;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
ct = current_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
/*
|
||||
* Create the new task's capture control block.
|
||||
*/
|
||||
nt = rtems_capture_create_capture_task (new_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, nt, RTEMS_CAPTURE_CREATE))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
|
||||
rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
|
||||
}
|
||||
|
||||
return 1 == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is started.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_start_task (rtems_tcb* current_task,
|
||||
rtems_tcb* started_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* st;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
ct = current_task->extensions[index];
|
||||
st = started_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (st == NULL)
|
||||
st = rtems_capture_create_capture_task (started_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, st, RTEMS_CAPTURE_START))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
|
||||
rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_init_stack_usage (st);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is restarted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_restart_task (rtems_tcb* current_task,
|
||||
rtems_tcb* restarted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* rt;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
ct = current_task->extensions[index];
|
||||
rt = restarted_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (rt == NULL)
|
||||
rt = rtems_capture_create_capture_task (restarted_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, rt, RTEMS_CAPTURE_RESTART))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
|
||||
rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_task_stack_usage (rt);
|
||||
rtems_capture_init_stack_usage (rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is deleted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_delete_task (rtems_tcb* current_task,
|
||||
rtems_tcb* deleted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* dt;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
ct = current_task->extensions[index];
|
||||
dt = deleted_task->extensions[index];
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
|
||||
if (dt == NULL)
|
||||
dt = rtems_capture_create_capture_task (deleted_task);
|
||||
|
||||
if (rtems_capture_trigger (ct, dt, RTEMS_CAPTURE_DELETE))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
|
||||
rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
|
||||
}
|
||||
|
||||
rtems_capture_task_stack_usage (dt);
|
||||
|
||||
/*
|
||||
* This task's tcb will be invalid. This signals the
|
||||
* task has been deleted.
|
||||
*/
|
||||
dt->tcb = 0;
|
||||
|
||||
rtems_capture_destroy_capture_task (dt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is begun.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_begin_task (rtems_tcb* begin_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* bt;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
bt = begin_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (bt == NULL)
|
||||
bt = rtems_capture_create_capture_task (begin_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, bt, RTEMS_CAPTURE_BEGIN))
|
||||
rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a task is exitted. That is
|
||||
* returned rather than was deleted.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_exitted_task (rtems_tcb* exitted_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* et;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
et = exitted_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (et == NULL)
|
||||
et = rtems_capture_create_capture_task (exitted_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, et, RTEMS_CAPTURE_EXITTED))
|
||||
rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
|
||||
|
||||
rtems_capture_task_stack_usage (et);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a termination request is identified.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_terminated_task (rtems_tcb* terminated_task)
|
||||
{
|
||||
/*
|
||||
* Get the capture task control block so we can trace this
|
||||
* event.
|
||||
*/
|
||||
rtems_capture_task_t* tt;
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
tt = terminated_task->extensions[index];
|
||||
|
||||
/*
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
|
||||
if (tt == NULL)
|
||||
tt = rtems_capture_create_capture_task (terminated_task);
|
||||
|
||||
if (rtems_capture_trigger (NULL, tt, RTEMS_CAPTURE_TERMINATED))
|
||||
rtems_capture_record (tt, RTEMS_CAPTURE_TERMINATED_EVENT);
|
||||
|
||||
rtems_capture_task_stack_usage (tt);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a context is switched.
|
||||
*/
|
||||
static void
|
||||
rtems_capture_switch_task (rtems_tcb* current_task,
|
||||
rtems_tcb* heir_task)
|
||||
{
|
||||
uint32_t flags = rtems_capture_get_flags();
|
||||
int index = rtems_capture_get_extension_index();
|
||||
|
||||
/*
|
||||
* Only perform context switch trace processing if tracing is
|
||||
* enabled.
|
||||
*/
|
||||
if (flags & RTEMS_CAPTURE_ON)
|
||||
{
|
||||
rtems_capture_time_t time;
|
||||
|
||||
/*
|
||||
* Get the cpature task control block so we can update the
|
||||
* reference and perform any watch or trigger functions.
|
||||
* The task pointers may not be known as the task may have
|
||||
* been created before the capture engine was open. Add them.
|
||||
*/
|
||||
rtems_capture_task_t* ct;
|
||||
rtems_capture_task_t* ht;
|
||||
|
||||
|
||||
if (_States_Is_dormant (current_task->current_state))
|
||||
{
|
||||
rtems_id ct_id = current_task->Object.id;
|
||||
ct = rtems_capture_find_capture_task( ct_id );
|
||||
}
|
||||
else
|
||||
{
|
||||
ct = current_task->extensions[index];
|
||||
|
||||
if (ct == NULL)
|
||||
ct = rtems_capture_create_capture_task (current_task);
|
||||
}
|
||||
|
||||
ht = heir_task->extensions[index];
|
||||
|
||||
if (ht == NULL)
|
||||
ht = rtems_capture_create_capture_task (heir_task);
|
||||
|
||||
/*
|
||||
* Update the execution time. Assume the time will not overflow
|
||||
* for now. This may need to change.
|
||||
*/
|
||||
rtems_capture_get_time (&time);
|
||||
|
||||
/*
|
||||
* We could end up with null pointers for both the current task
|
||||
* and the heir task.
|
||||
*/
|
||||
|
||||
if (ht)
|
||||
{
|
||||
ht->in++;
|
||||
ht->time_in = time;
|
||||
}
|
||||
|
||||
if (ct)
|
||||
{
|
||||
ct->out++;
|
||||
if (ct->time_in)
|
||||
ct->time += time - ct->time_in;
|
||||
}
|
||||
|
||||
if (rtems_capture_trigger (ct, ht, RTEMS_CAPTURE_SWITCH))
|
||||
{
|
||||
rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
|
||||
rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
195
cpukit/libmisc/capture/captureimpl.h
Normal file
195
cpukit/libmisc/capture/captureimpl.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* @file rtems/captureimpl.h
|
||||
*
|
||||
* @brief Capture Implementation file
|
||||
*
|
||||
* This file contains an interface between the capture engine and
|
||||
* capture user extension methods.
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Copyright Objective Design Systems Pty Ltd, 2002
|
||||
All rights reserved Objective Design Systems Pty Ltd, 2002
|
||||
Chris Johns (ccj@acm.org)
|
||||
|
||||
COPYRIGHT (c) 1989-2014.
|
||||
On-Line Applications Research Corporation (OAR).
|
||||
|
||||
The license and distribution terms for this file may be
|
||||
found in the file LICENSE in this distribution.
|
||||
|
||||
This software with is provided ``as is'' and with NO WARRANTY.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
RTEMS Performance Monitoring and Measurement Framework.
|
||||
This is the Capture Engine component.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CAPTUREIMPL_H_
|
||||
#define __CAPTUREIMPL_H_
|
||||
|
||||
|
||||
/**@{*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "capture.h"
|
||||
|
||||
/*
|
||||
* 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_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)
|
||||
|
||||
/**
|
||||
* @brief Capture set extension index.
|
||||
*
|
||||
* This function is used to set the extension index
|
||||
* for the capture engine.
|
||||
*
|
||||
* @param[in] index specifies the extension index to be
|
||||
* used for capture engine data.
|
||||
*/
|
||||
void rtems_capture_set_extension_index(int index);
|
||||
|
||||
/**
|
||||
* @brief Capture get extension index.
|
||||
*
|
||||
* This function rturns the extension index for the
|
||||
* capture engine.
|
||||
*
|
||||
* @retval This method returns the extension index.
|
||||
*/
|
||||
int rtems_capture_get_extension_index(void);
|
||||
|
||||
/**
|
||||
* @brief Capture get flags.
|
||||
*
|
||||
* This function gets the current flag settings
|
||||
* for the capture engine.
|
||||
*
|
||||
* @retval This method returns the global capture
|
||||
* flags.
|
||||
*
|
||||
*/
|
||||
uint32_t rtems_capture_get_flags(void);
|
||||
|
||||
/**
|
||||
* @brief Capture set flags.
|
||||
*
|
||||
* This function sets a flag in the capture engine
|
||||
*
|
||||
* @param[in] mask specifies the flag to set
|
||||
*/
|
||||
void rtems_capture_set_flags(uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Capture user extension open.
|
||||
*
|
||||
* This function creates the capture user extensions.
|
||||
*
|
||||
*
|
||||
* @retval This method returns RTEMS_SUCCESSFUL upon successful
|
||||
* creation of the user extensions.
|
||||
*/
|
||||
rtems_status_code rtems_capture_user_extension_open(void);
|
||||
|
||||
/**
|
||||
* @brief Capture user extension close.
|
||||
*
|
||||
* This function closes the capture user extensions.
|
||||
*
|
||||
* @retval This method returns RTEMS_SUCCESSFUL upon a successful
|
||||
* delete of the user extensions.
|
||||
*/
|
||||
rtems_status_code rtems_capture_user_extension_close(void);
|
||||
|
||||
/**
|
||||
* @brief Capture find capture task.
|
||||
*
|
||||
* This function finds the capture task control block
|
||||
*
|
||||
* @param[in] ct_id specifies the task_id
|
||||
*
|
||||
* @retval This method returns the capture task control block associated
|
||||
* with the given task id.
|
||||
*/
|
||||
rtems_capture_task_t* rtems_capture_find_capture_task( rtems_id ct_id );
|
||||
|
||||
/**
|
||||
* @brief Capture create capture task control block.
|
||||
*
|
||||
* This function create the capture task control block
|
||||
*
|
||||
* @param[in] new_task specifies the rtems thread control block
|
||||
*
|
||||
* @retval This method returns a capture task control block.
|
||||
*/
|
||||
rtems_capture_task_t* rtems_capture_create_capture_task (rtems_tcb* new_task);
|
||||
|
||||
/**
|
||||
* @brief Capture trigger.
|
||||
*
|
||||
* This function checks if we have triggered or if this event is a
|
||||
* cause of a trigger.
|
||||
*
|
||||
* @param[in] ft specifies specifices the capture from task
|
||||
* @param[in] tt specifies specifices the capture to task
|
||||
* @param[in] events specifies the events
|
||||
*
|
||||
* @retval This method returns true if we have triggered or
|
||||
* if the event is a cause of a trigger.
|
||||
*/
|
||||
bool rtems_capture_trigger (rtems_capture_task_t* ft,
|
||||
rtems_capture_task_t* tt,
|
||||
uint32_t events);
|
||||
/**
|
||||
* @brief Capture initialize stack usage
|
||||
*
|
||||
* This function setups a stack so its usage can be monitored.
|
||||
*
|
||||
* @param[in] task specifies the capture task block
|
||||
*/
|
||||
void rtems_capture_init_stack_usage (rtems_capture_task_t* task);
|
||||
|
||||
/**
|
||||
* @brief Capture destroy task.
|
||||
*
|
||||
* This function destroy the task structure if the reference count
|
||||
* is 0 and the tcb has been cleared signalling the task has been
|
||||
* deleted.
|
||||
*
|
||||
* @param[in] task specifies the capture task block
|
||||
*/
|
||||
void rtems_capture_destroy_capture_task (rtems_capture_task_t* task);
|
||||
|
||||
/**
|
||||
* @brief .
|
||||
*
|
||||
* This function returns the current time. If a handler is provided
|
||||
* by the user the time is gotten from that.
|
||||
*
|
||||
* @param[in] time specifies the capture time
|
||||
*
|
||||
* @retval This method returns a nano-second time if no user handler
|
||||
* is provided. Otherwise, it returns a resolution defined by the handler.
|
||||
*/
|
||||
void rtems_capture_get_time (rtems_capture_time_t* time);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user