📄 capture.c
字号:
/* ------------------------------------------------------------------------ $Id: capture.c,v 1.3.2.1 2003/07/08 08:36:36 ralf Exp $ ------------------------------------------------------------------------ Copyright Objective Design Systems Pty Ltd, 2002 All rights reserved Objective Design Systems Pty Ltd, 2002 Chris Johns (ccj@acm.org) COPYRIGHT (c) 1989-1998. 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.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "capture.h"#include <rtems/score/states.inl>#include <rtems/score/wkspace.h>#include <rtems/score/wkspace.inl>/* * These events are always recorded and are not part of the * watch filters. */#define RTEMS_CAPTURE_RECORD_EVENTS (RTEMS_CAPTURE_CREATED_BY_EVENT | \ RTEMS_CAPTURE_CREATED_EVENT | \ RTEMS_CAPTURE_STARTED_BY_EVENT | \ RTEMS_CAPTURE_STARTED_EVENT | \ RTEMS_CAPTURE_RESTARTED_BY_EVENT | \ RTEMS_CAPTURE_RESTARTED_EVENT | \ RTEMS_CAPTURE_DELETED_BY_EVENT | \ RTEMS_CAPTURE_DELETED_EVENT | \ RTEMS_CAPTURE_BEGIN_EVENT | \ RTEMS_CAPTURE_EXITTED_EVENT)/* * Global capture flags. */#define RTEMS_CAPTURE_ON (1 << 0)#define RTEMS_CAPTURE_NO_MEMORY (1 << 1)#define RTEMS_CAPTURE_OVERFLOW (1 << 2)#define RTEMS_CAPTURE_TRIGGERED (1 << 3)#define RTEMS_CAPTURE_READER_ACTIVE (1 << 4)#define RTEMS_CAPTURE_READER_WAITING (1 << 5)#define RTEMS_CAPTURE_GLOBAL_WATCH (1 << 6)/* * RTEMS Capture Data. */static rtems_capture_record_t* capture_records;static rtems_unsigned32 capture_size;static rtems_unsigned32 capture_count;static rtems_capture_record_t* capture_in;static rtems_unsigned32 capture_out;static rtems_unsigned32 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;static rtems_unsigned32 capture_tick_period;static rtems_id capture_reader;/* * RTEMS Event text. */static const char* capture_event_text[] ={ "CREATED_BY", "CREATED", "STARTED_BY", "STARTED", "RESTARTED_BY", "RESTARTED", "DELETED_BY", "DELETED", "BEGIN", "EXITTED", "SWITCHED_OUT", "SWITCHED_IN", "TIMESTAMP"};/* * rtems_capture_get_time * * DESCRIPTION: * * This function returns the current time. If a handler is provided * by the user get the time from that. */static inline void rtems_capture_get_time (rtems_unsigned32* ticks, rtems_unsigned32* tick_offset){ if (capture_timestamp) capture_timestamp (ticks, tick_offset); else { *ticks = _Watchdog_Ticks_since_boot; *tick_offset = 0; }}/* * rtems_capture_match_names * * DESCRIPTION: * * This function compares rtems_names. It protects the * capture engine from a change to the way names are supported * in RTEMS. * */static inline rtems_booleanrtems_capture_match_names (rtems_name lhs, rtems_name rhs){ return lhs == rhs;}/* * rtems_capture_dup_name * * DESCRIPTION: * * This function duplicates an rtems_names. It protects the * cpature engine from a change to the way names are supported * in RTEMS. * */static inline voidrtems_capture_dup_name (rtems_name* dst, rtems_name src){ *dst = src;}/* * rtems_capture_name_in_group * * DESCRIPTION: * * This function sees if a name is in a group of names. * */static inline rtems_booleanrtems_capture_name_in_group (rtems_name task, rtems_name* tasks){ if (tasks) { int i; for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++) if (rtems_capture_match_names (task, *tasks++)) return 1; } return 0;}/* * rtems_capture_match_name_id * * DESCRIPTION: * * This function matches a name and/or id. */static inline rtems_booleanrtems_capture_match_name_id (rtems_name lhs_name, rtems_id lhs_id, rtems_name rhs_name, rtems_id rhs_id){ /* * The left hand side name or id could be 0 which means a wildcard. */ if ((lhs_name == 0) && (lhs_id == rhs_id)) return 1; else if ((lhs_id == 0) || (lhs_id == rhs_id)) { if (rtems_capture_match_names (lhs_name, rhs_name)) return 1; } return 0;}/* * rtems_capture_init_stack_usage * * DESCRIPTION: * * This function setups a stack so its usage can be monitored. */static inline voidrtems_capture_init_stack_usage (rtems_capture_task_t* task){ if (task->tcb) { rtems_unsigned32* s; rtems_unsigned32 i; task->stack_size = task->tcb->Start.Initial_stack.size; task->stack_clean = task->stack_size; s = task->tcb->Start.Initial_stack.area; for (i = 0; i < (task->stack_size - 128); i += 4) *(s++) = 0xdeaddead; }}/* * rtems_capture_find_control * * DESCRIPTION: * * This function searches for a trigger given a name. * */static inline rtems_capture_control_t*rtems_capture_find_control (rtems_name name, rtems_id id){ rtems_capture_control_t* control; for (control = capture_controls; control != NULL; control = control->next) if (rtems_capture_match_name_id (name, id, control->name, control->id)) break; return control;}/* * rtems_capture_create_control * * DESCRIPTION: * * This function creates a capture control for the capture engine. * */static inline rtems_capture_control_t*rtems_capture_create_control (rtems_name name, rtems_id id){ rtems_interrupt_level level; rtems_capture_control_t* control; rtems_capture_task_t* task; if ((name == 0) && (id == 0)) return NULL; control = rtems_capture_find_control (name, id); if (control == NULL) { control = _Workspace_Allocate (sizeof (rtems_capture_control_t)); if (control == NULL) { capture_flags |= RTEMS_CAPTURE_NO_MEMORY; return NULL; } control->name = name; control->id = id; control->flags = 0; memset (control->from, 0, sizeof (control->from)); memset (control->from_id, 0, sizeof (control->from_id)); rtems_interrupt_disable (level); control->next = capture_controls; capture_controls = control; /* * We need to scan the task list as set the control to the * tasks. */ for (task = capture_tasks; task != NULL; task = task->next) if (rtems_capture_match_name_id (name, id, task->name, task->id)) task->control = control; rtems_interrupt_enable (level); } return control;}/* * rtems_capture_create_capture_task * * DESCRIPTION: * * This function create the task control. * */static inline rtems_capture_task_t*rtems_capture_create_capture_task (rtems_tcb* new_task){ rtems_interrupt_level level; rtems_capture_task_t* task; rtems_capture_control_t* control; task = _Workspace_Allocate (sizeof (rtems_capture_task_t)); if (task == NULL) { capture_flags |= RTEMS_CAPTURE_NO_MEMORY; return NULL; } rtems_capture_dup_name (&task->name, ((rtems_name) new_task->Object.name)); task->id = new_task->Object.id; task->flags = 0; task->in = 0; task->out = 0; task->tcb = new_task; task->ticks = 0; task->tick_offset = 0; task->ticks_in = 0; task->tick_offset_in = 0; task->control = 0; task->last_ticks = 0; task->last_tick_offset = 0; task->tcb->extensions[capture_extension_index] = task; task->start_priority = new_task->Start.initial_priority; task->stack_size = new_task->Start.Initial_stack.size; task->stack_clean = task->stack_size; rtems_interrupt_disable (level); task->next = capture_tasks; capture_tasks = task; rtems_interrupt_enable (level); /* * We need to scan the default control list to initialise * this control. */ for (control = capture_controls; control != NULL; control = control->next) if (rtems_capture_match_name_id (control->name, control->id, task->name, task->id)) task->control = control; return task;}/* * rtems_capture_record * * DESCRIPTION: * * This function records a capture record into the capture buffer. * */static inline voidrtems_capture_record (rtems_capture_task_t* task, rtems_unsigned32 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) { rtems_capture_control_t* control; control = task->control; /* * Capure the record if we have an event that is always * captured, or the task's real priority is greater than the * watch ceiling, and the global watch or task watch is enabled. */ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) || ((task->tcb->real_priority >= capture_ceiling) && (task->tcb->real_priority <= capture_floor) && ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) || (control && (control->flags & RTEMS_CAPTURE_WATCH))))) { rtems_interrupt_level level; rtems_interrupt_disable (level); 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->ticks, &capture_in->tick_offset); if (capture_in == &capture_records[capture_size - 1]) capture_in = capture_records; else capture_in++; } else capture_flags |= RTEMS_CAPTURE_OVERFLOW; rtems_interrupt_enable (level); } }}/* * rtems_capture_create_task * * DESCRIPTION: * * This function is called when a task is created. * */static rtems_booleanrtems_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 ponters 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 we are logging then record this fact. */ rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT); rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT); return 1 == 1;}/* * rtems_capture_start_task * * DESCRIPTION: * * This function is called when a task is started. * */static rtems_extensionrtems_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 ponters 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); rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT); rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT); rtems_capture_init_stack_usage (st);}/* * rtems_capture_restart_task * * DESCRIPTION: * * This function is called when a task is restarted. * */static rtems_extensionrtems_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -