📄 capture.c
字号:
/* * rtems_capture_watch_del * * DESCRIPTION: * * This function removes a watch for a specific task given a name. The task * description will still exist if referenced by a trace record in the trace * buffer or a global watch is defined. */rtems_status_codertems_capture_watch_del (rtems_name name, rtems_id id){ rtems_interrupt_level level; rtems_capture_control_t* control; rtems_capture_control_t** prev_control; rtems_capture_task_t* task; rtems_boolean found = 0; /* * Should this test be for wildcards ? */ for (prev_control = &capture_controls, control = capture_controls; control != NULL; ) { if (rtems_capture_match_name_id (name, id, control->name, control->id)) { rtems_interrupt_disable (level); for (task = capture_tasks; task != NULL; task = task->next) if (task->control == control) task->control = 0; *prev_control = control->next; rtems_interrupt_enable (level); _Workspace_Free (control); control = *prev_control; found = 1; } else { prev_control = &control->next; control = control->next; } } if (found) return RTEMS_SUCCESSFUL; return RTEMS_INVALID_NAME;}/* * rtems_capture_watch_set * * DESCRIPTION: * * This function allows control of a watch. The watch can be enabled or * disabled. */rtems_status_codertems_capture_watch_ctrl (rtems_name name, rtems_id id, rtems_boolean enable){ rtems_interrupt_level level; rtems_capture_control_t* control; rtems_boolean found = 0; /* * Find the control and then set the watch. It must exist before it can * be controlled. */ for (control = capture_controls; control != NULL; control = control->next) { if (rtems_capture_match_name_id (name, id, control->name, control->id)) { rtems_interrupt_disable (level); if (enable) control->flags |= RTEMS_CAPTURE_WATCH; else control->flags &= ~RTEMS_CAPTURE_WATCH; rtems_interrupt_enable (level); found = 1; } } if (found) return RTEMS_SUCCESSFUL; return RTEMS_INVALID_NAME;}/* * rtems_capture_watch_global * * DESCRIPTION: * * This function allows control of a global watch. The watch can be enabled or * disabled. A global watch configures all tasks below the ceiling and above * the floor to be traced. */rtems_status_codertems_capture_watch_global (rtems_boolean enable){ rtems_interrupt_level level; rtems_interrupt_disable (level); /* * We need to keep specific and global watches separate so * a global enable/disable does not lose a specific watch. */ if (enable) capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH; else capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH; rtems_interrupt_enable (level); return RTEMS_SUCCESSFUL;}/* * rtems_capture_watch_global_on * * DESCRIPTION: * * This function returns the global watch state. */rtems_booleanrtems_capture_watch_global_on (){ return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;}/* * rtems_capture_watch_ceiling * * DESCRIPTION: * * This function sets a watch ceiling. Tasks at or greating that the * ceiling priority are not watched. This is a simple way to monitor * an application and exclude system tasks running at a higher * priority level. */rtems_status_codertems_capture_watch_ceiling (rtems_task_priority ceiling){ capture_ceiling = ceiling; return RTEMS_SUCCESSFUL;}/* * rtems_capture_watch_get_ceiling * * DESCRIPTION: * * This function gets the watch ceiling. */rtems_task_priorityrtems_capture_watch_get_ceiling (){ return capture_ceiling;}/* * rtems_capture_watch_floor * * DESCRIPTION: * * This function sets a watch floor. Tasks at or less that the * floor priority are not watched. This is a simple way to monitor * an application and exclude system tasks running at a lower * priority level. */rtems_status_codertems_capture_watch_floor (rtems_task_priority floor){ capture_floor = floor; return RTEMS_SUCCESSFUL;}/* * rtems_capture_watch_get_floor * * DESCRIPTION: * * This function gets the watch floor. */rtems_task_priorityrtems_capture_watch_get_floor (){ return capture_floor;}/* * rtems_capture_set_trigger * * DESCRIPTION: * * This function sets an edge trigger. Left is the left side of * the edge and right is right side of the edge. The trigger type * can be - * * FROM_ANY : a switch from any task to the right side of the edge. * TO_ANY : a switch from the left side of the edge to any task. * FROM_TO : a switch from the left side of the edge to the right * side of the edge. * * This set trigger routine will create a capture control for the * target task. The task list is searched and any existing tasks * are linked to the new control. * * We can have a number of tasks that have the same name so we * search using names. This means a number of tasks can be * linked to single control. */rtems_status_codertems_capture_set_trigger (rtems_name from, rtems_id from_id, rtems_name to, rtems_id to_id, rtems_capture_trigger_t trigger){ rtems_capture_control_t* control; int i; /* * Find the capture control blocks for the from and to * tasks. */ if (trigger == rtems_capture_to_any) { control = rtems_capture_create_control (from, from_id); if (control == NULL) return RTEMS_NO_MEMORY; control->flags |= RTEMS_CAPTURE_TO_ANY; } if ((trigger == rtems_capture_from_to) || (trigger == rtems_capture_from_any)) { control = rtems_capture_create_control (to, to_id); if (control == NULL) return RTEMS_NO_MEMORY; if (trigger == rtems_capture_from_any) control->flags |= RTEMS_CAPTURE_FROM_ANY; else { control->flags |= RTEMS_CAPTURE_FROM_TO; for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++) { if (control->from[i] == 0) { control->from[i] = from; control->from_id[i] = from_id; break; } } } } return RTEMS_SUCCESSFUL;}/* * rtems_capture_read * * DESCRIPTION: * * This function reads a number of records from the capture buffer. * The user can optionally block and wait until the buffer as a * specific number of records available or a specific time has * elasped. * * The function returns the number of record that is has that are * in a continous block of memory. If the number of available records * wrap then only those records are provided. This removes the need for * caller to be concerned about buffer wrappings. If the number of * requested records cannot be met due to the wrapping of the records * less than the specified number will be returned. * * The user must release the records. This is achieved with a call to * rtems_capture_release. Calls this function without a release will * result in at least the same number of records being released. * * The 'threshold' parameter is the number of records that must be * captured before returning. If a timeout period is specified (non-0) * any captured records will be returned. These parameters stop * thrashing occuring for a small number of records, yet allows * a user configured latiency to be applied for single events. * * The 'timeout' parameter is in micro-seconds. A value of 0 will disable * the timeout. * */rtems_status_codertems_capture_read (rtems_unsigned32 threshold, rtems_unsigned32 timeout, rtems_unsigned32* read, rtems_capture_record_t** recs){ rtems_interrupt_level level; rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_unsigned32 count; *read = 0; *recs = NULL; rtems_interrupt_disable (level); /* * Only one reader is allowed. */ if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE) { rtems_interrupt_enable (level); return RTEMS_RESOURCE_IN_USE; } capture_flags |= RTEMS_CAPTURE_READER_ACTIVE; *read = count = capture_count; rtems_interrupt_enable (level); *recs = &capture_records[capture_out]; for (;;) { /* * See if the count wraps the end of the record buffer. */ if (count && ((capture_out + count) >= capture_size)) *read = capture_size - capture_out; /* * Do we have a threshold and the current count has not wrapped * around the end of the capture record buffer ? */ if ((*read == count) && threshold) { /* * Do we have enough records ? */ if (*read < threshold) { rtems_event_set event_out; rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader); rtems_interrupt_disable (level); capture_flags |= RTEMS_CAPTURE_READER_WAITING; rtems_interrupt_enable (level); sc = rtems_event_receive (RTEMS_EVENT_0, RTEMS_WAIT | RTEMS_EVENT_ANY, TOD_MICROSECONDS_TO_TICKS (timeout), &event_out); /* * Let the user handle all other sorts of errors. This may * not be the best solution, but oh well, it will do for * now. */ if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT)) break; rtems_interrupt_disable (level); *read = count = capture_count; rtems_interrupt_enable (level); continue; } } /* * Always out if we reach here. To loop use continue. */ break; } rtems_interrupt_disable (level); capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE; rtems_interrupt_enable (level); return sc;}/* * rtems_capture_release * * DESCRIPTION: * * This function releases the requested number of record slots back * to the capture engine. The count must match the number read. */rtems_status_codertems_capture_release (rtems_unsigned32 count){ rtems_interrupt_level level; rtems_interrupt_disable (level); if (count > capture_count) count = capture_count; capture_count -= count; capture_out = (capture_count + count) % capture_size; rtems_interrupt_enable (level); return RTEMS_SUCCESSFUL;}/* * rtems_capture_tick_time * * DESCRIPTION: * * This function returns the tick period in nano-seconds. */rtems_unsigned32rtems_capture_tick_time (){ return capture_tick_period;}/* * rtems_capture_event_text * * DESCRIPTION: * * This function returns a string for an event based on the bit in the * event. The functions takes the bit offset as a number not the bit * set in a bit map. */const char*rtems_capture_event_text (int event){ if ((event < RTEMS_CAPTURE_EVENT_START) || (event > RTEMS_CAPTURE_EVENT_END)) return "invalid event id"; return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];}/* * rtems_capture_get_task_list * * DESCRIPTION: * * This function returns the head of the list of tasks that the * capture engine has detected. */rtems_capture_task_t*rtems_capture_get_task_list (){ return capture_tasks;}/* * rtems_capture_task_stack_usage * * DESCRIPTION: * * This function updates the stack usage. The task control block * is updated. */rtems_unsigned32rtems_capture_task_stack_usage (rtems_capture_task_t* task){ if (task->tcb) { rtems_unsigned32* st; rtems_unsigned32* s; /* * @todo: Assumes all stacks move the same way. */ st = task->tcb->Start.Initial_stack.area + task->stack_size; s = task->tcb->Start.Initial_stack.area; while (s < st) { if (*s != 0xdeaddead) break; s++; } task->stack_clean = s - (rtems_unsigned32*) task->tcb->Start.Initial_stack.area; } return task->stack_clean;}/* * rtems_capture_get_control_list * * DESCRIPTION: * * This function returns the head of the list of control in the * capture engine. */rtems_capture_control_t*rtems_capture_get_control_list (){ return capture_controls;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -