diff options
Diffstat (limited to 'cpukit/libmisc/capture/capture-cli.c')
-rw-r--r-- | cpukit/libmisc/capture/capture-cli.c | 379 |
1 files changed, 216 insertions, 163 deletions
diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c index 2aa7c9c229..e911b2eacb 100644 --- a/cpukit/libmisc/capture/capture-cli.c +++ b/cpukit/libmisc/capture/capture-cli.c @@ -35,12 +35,28 @@ #include <rtems.h> #include <rtems/capture-cli.h> #include <rtems/monitor.h> - +#include <rtems/cpuuse.h> +# #define RC_UNUSED __attribute__((unused)) #define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (20) /* + * Counter used to count the number of active tasks. + */ +static int rtems_capture_cli_task_count = 0; + +/* + * Array of tasks sorted by load. + */ +static rtems_tcb* rtems_capture_cli_load_tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1]; + +/* + * The load for each tcb at the moment rtems_capture_cli_load_tasks was generated. + */ +static unsigned long long rtems_capture_cli_load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1]; + +/* * The user capture timestamper. */ static rtems_capture_timestamp capture_timestamp; @@ -233,6 +249,104 @@ rtems_capture_cli_print_timestamp (uint64_t uptime) fprintf (stdout, "%5lu:%02lu:%02lu.%09lu", hours, minutes, seconds, nanosecs); } +static void +rtems_capture_cli_print_task (rtems_tcb *tcb) +{ + rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); + rtems_task_priority floor = rtems_capture_watch_get_floor (); + rtems_task_priority priority; + int length; + + priority = rtems_capture_task_real_priority (tcb); + + fprintf (stdout, " "); + rtems_monitor_dump_id (rtems_capture_task_id (tcb)); + fprintf (stdout, " "); + rtems_monitor_dump_name (rtems_capture_task_id (tcb)); + fprintf (stdout, " "); + rtems_monitor_dump_priority (rtems_capture_task_start_priority (tcb)); + fprintf (stdout, " "); + rtems_monitor_dump_priority (rtems_capture_task_real_priority (tcb)); + fprintf (stdout, " "); + rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tcb)); + fprintf (stdout, " "); + length = rtems_monitor_dump_state (rtems_capture_task_state (tcb)); + fprintf (stdout, "%*c", 14 - length, ' '); + fprintf (stdout, " %c%c", + 'a', + rtems_capture_task_flags (tcb) & RTEMS_CAPTURE_TRACED ? 't' : '-'); + + if ((floor > ceiling) && (ceiling > priority)) + fprintf (stdout, "--"); + else + { + uint32_t flags = rtems_capture_task_control_flags (tcb); + fprintf (stdout, "%c%c", + rtems_capture_task_control (tcb) ? + (flags & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-', + rtems_capture_watch_global_on () ? 'g' : '-'); + } + fprintf (stdout, "\n"); +} +static void +rtems_caputure_cli_print_record_std(rtems_capture_record_t* rec, uint64_t diff) +{ + uint32_t event; + int e; + + event = rec->events >> RTEMS_CAPTURE_EVENT_START; + + for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++) + { + if (event & 1) + { + rtems_capture_cli_print_timestamp (rec->time); + fprintf (stdout, " %9" PRId64 " ", diff); + rtems_monitor_dump_id (rec->task_id); + fprintf(stdout, " %3" PRId32 " %3" PRId32 " %s\n", + (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, + (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, + rtems_capture_event_text (e)); + } + event >>= 1; + } +} + +static void +rtems_caputre_cli_print_record_task(rtems_capture_record_t* rec) +{ + rtems_capture_task_record_t* task_rec = (rtems_capture_task_record_t*) rec; + + rtems_capture_cli_print_timestamp (rec->time); + fprintf (stdout, " "); + rtems_monitor_dump_id (rec->task_id); + fprintf (stdout, " %c%c%c%c", + (char) (task_rec->name >> 24) & 0xff, + (char) (task_rec->name >> 16) & 0xff, + (char) (task_rec->name >> 8) & 0xff, + (char) (task_rec->name >> 0) & 0xff); + fprintf (stdout, " %3" PRId32 " %3" PRId32 "\n", + task_rec->start_priority, + task_rec->stack_size); +} + +/* + * rtems_capture_cli_count_tasks + * + * DESCRIPTION: + * + * This function is called for each tcb and counts the + * number of tasks. + * + */ + +static void +rtems_capture_cli_count_tasks (rtems_tcb *tcb) +{ + rtems_capture_cli_task_count++; +} + + /* * rtems_capture_cli_task_list * @@ -248,71 +362,49 @@ rtems_capture_cli_task_list (int argc RC_UNUSED, const rtems_monitor_command_arg_t* command_arg RC_UNUSED, bool verbose RC_UNUSED) { - rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); - rtems_task_priority floor = rtems_capture_watch_get_floor (); - rtems_capture_task_t* task = rtems_capture_get_task_list (); - int count = rtems_capture_task_count (); rtems_capture_time_t uptime; rtems_capture_time (&uptime); + rtems_capture_cli_task_count = 0; + rtems_iterate_over_all_threads (rtems_capture_cli_count_tasks); + fprintf (stdout, "uptime: "); rtems_capture_cli_print_timestamp (uptime); - fprintf (stdout, "\ntotal %i\n", count); - - while (task) - { - rtems_task_priority priority; - int32_t stack_used; - int32_t time_used; - int length; + fprintf (stdout, "\ntotal %i\n", rtems_capture_cli_task_count); + rtems_iterate_over_all_threads (rtems_capture_cli_print_task); +} - stack_used = rtems_capture_task_stack_usage (task); - if (stack_used) - stack_used = (stack_used * 100) / rtems_capture_task_stack_size (task); +static void +rtems_capture_cli_task_sort (rtems_tcb* tcb) +{ + int i; + int j; - if (stack_used > 100) - stack_used = 100; + if (tcb) + { + rtems_capture_time_t l = tcb->cpu_time_used; - time_used = (rtems_capture_task_time (task) * 100) / uptime; + rtems_capture_cli_task_count++; - if (time_used > 100) - time_used = 100; + for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++) + { + if (rtems_capture_cli_load_tasks[i]) + { + if ((l == 0) || (l < rtems_capture_cli_load[i])) + continue; - priority = rtems_capture_task_real_priority (task); + for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1); j >= i; j--) + { + rtems_capture_cli_load_tasks[j + 1] = rtems_capture_cli_load_tasks[j]; + rtems_capture_cli_load[j + 1] = rtems_capture_cli_load[j]; + } + } - fprintf (stdout, " "); - rtems_monitor_dump_id (rtems_capture_task_id (task)); - fprintf (stdout, " "); - rtems_monitor_dump_name (rtems_capture_task_id (task)); - fprintf (stdout, " "); - rtems_monitor_dump_priority (rtems_capture_task_start_priority (task)); - fprintf (stdout, " "); - rtems_monitor_dump_priority (rtems_capture_task_real_priority (task)); - fprintf (stdout, " "); - rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task)); - fprintf (stdout, " "); - length = rtems_monitor_dump_state (rtems_capture_task_state (task)); - fprintf (stdout, "%*c", 14 - length, ' '); - fprintf (stdout, " %c%c", - rtems_capture_task_valid (task) ? 'a' : 'd', - rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED ? 't' : '-'); - - if ((floor > ceiling) && (ceiling > priority)) - fprintf (stdout, "--"); - else - { - uint32_t flags = rtems_capture_task_control_flags (task); - fprintf (stdout, "%c%c", - rtems_capture_task_control (task) ? - (flags & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-', - rtems_capture_watch_global_on () ? 'g' : '-'); + rtems_capture_cli_load_tasks[i] = tcb; + rtems_capture_cli_load[i] = l; + break; } - fprintf (stdout, " %3" PRId32 "%% %3" PRId32 "%% ", stack_used, time_used); - rtems_capture_cli_print_timestamp (rtems_capture_task_time (task)); - fprintf (stdout, "\n"); - - task = rtems_capture_next_task (task); } } @@ -328,26 +420,22 @@ rtems_capture_cli_task_list (int argc RC_UNUSED, static void rtems_capture_cli_task_load_thread (rtems_task_argument arg) { + rtems_tcb* tcb; rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); rtems_task_priority floor = rtems_capture_watch_get_floor (); int last_count = 0; FILE* pstdout = (FILE*) arg; + int i; + int j; fileno(stdout); stdout = pstdout; while (true) { - rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1]; - unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1]; - rtems_capture_task_t* task; - rtems_capture_time_t uptime; - rtems_capture_time_t total_time; - int count = 0; - int i; - int j; - - rtems_capture_time (&uptime); + Timestamp_Control uptime, total, ran, uptime_at_last_reset; + uint32_t seconds, nanoseconds; + size_t size; cli_load_thread_active = 1; @@ -356,114 +444,98 @@ rtems_capture_cli_task_load_thread (rtems_task_argument arg) * into our local arrays. We only handle a limited number of * tasks. */ + size = sizeof (rtems_capture_cli_load_tasks); + memset (rtems_capture_cli_load_tasks, 0, size); + memset (rtems_capture_cli_load, 0, sizeof (rtems_capture_cli_load)); - memset (tasks, 0, sizeof (tasks)); - memset (load, 0, sizeof (load)); - - task = rtems_capture_get_task_list (); + _Timestamp_Set_to_zero( &total ); + uptime_at_last_reset = CPU_usage_Uptime_at_last_reset; + _TOD_Get_uptime( &uptime ); + seconds = _Timestamp_Get_seconds( &uptime ); + nanoseconds = _Timestamp_Get_nanoseconds( &uptime ) / + TOD_NANOSECONDS_PER_MICROSECOND; - total_time = 0; - - while (task) - { - if (rtems_capture_task_valid (task)) - { - rtems_capture_time_t l = rtems_capture_task_delta_time (task); - - count++; - - total_time += l; - - for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++) - { - if (tasks[i]) - { - if ((l == 0) || (l < load[i])) - continue; - - for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1); j >= i; j--) - { - tasks[j + 1] = tasks[j]; - load[j + 1] = load[j]; - } - } - - tasks[i] = task; - load[i] = l; - break; - } - } - task = rtems_capture_next_task (task); - } + rtems_iterate_over_all_threads (rtems_capture_cli_task_sort); fprintf (stdout, "\x1b[H\x1b[J Press ENTER to exit.\n\n"); fprintf (stdout, "uptime: "); - rtems_capture_cli_print_timestamp (uptime); + fprintf (stdout, "%7" PRIu32 ".%06" PRIu32 "\n", seconds, nanoseconds); fprintf (stdout, "\n\n" - " PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n"); + " PID NAME RPRI CPRI STATE EXEC TIME %%CPU\n"); - if (count > last_count) - j = count; + if (rtems_capture_cli_task_count > last_count) + j = rtems_capture_cli_task_count; else j = last_count; for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++) { rtems_task_priority priority; - int stack_used; - int task_load; - int k; + Timestamp_Control last; + uint32_t ival, fval; - if (!tasks[i]) + if (!rtems_capture_cli_load_tasks[i]) break; j--; - stack_used = rtems_capture_task_stack_usage (tasks[i]); - if (stack_used) - stack_used = (stack_used * 100) / rtems_capture_task_stack_size (tasks[i]); - - if (stack_used > 100) - stack_used = 100; - - task_load = (int) ((load[i] * 100000) / total_time); + /* + * If this is the currently executing thread, account for time + * since the last context switch. + */ + tcb = rtems_capture_cli_load_tasks[i]; + ran = rtems_capture_cli_load[i]; + if ( _Thread_Get_time_of_last_context_switch( tcb, &last ) ) { + Timestamp_Control used; + _TOD_Get_uptime( &uptime ); + _Timestamp_Subtract( &last, &uptime, &used ); + _Timestamp_Add_to( &ran, &used ); + } else { + _TOD_Get_uptime( &uptime ); + } + _Timestamp_Subtract( &uptime_at_last_reset, &uptime, &total ); + _Timestamp_Divide( &ran, &total, &ival, &fval ); + seconds = _Timestamp_Get_seconds( &ran ); + nanoseconds = _Timestamp_Get_nanoseconds( &ran ) / + TOD_NANOSECONDS_PER_MICROSECOND; - priority = rtems_capture_task_real_priority (tasks[i]); + priority = rtems_capture_task_real_priority (tcb); fprintf (stdout, "\x1b[K"); - rtems_monitor_dump_id (rtems_capture_task_id (tasks[i])); + rtems_monitor_dump_id (rtems_capture_task_id (tcb)); fprintf (stdout, " "); - rtems_monitor_dump_name (rtems_capture_task_id (tasks[i])); + rtems_monitor_dump_name (rtems_capture_task_id (tcb)); fprintf (stdout, " "); rtems_monitor_dump_priority (priority); fprintf (stdout, " "); - rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i])); + rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tcb)); fprintf (stdout, " "); - k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i])); - fprintf (stdout, "%*c %3i.%03i%% ", 14 - k, ' ', - task_load / 1000, task_load % 1000); - fprintf (stdout, "%3i%% %c%c", stack_used, - rtems_capture_task_valid (tasks[i]) ? 'a' : 'd', - rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED ? 't' : '-'); + rtems_monitor_dump_state (rtems_capture_task_state (tcb)); + fprintf (stdout, + "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 , + seconds, nanoseconds, ival, fval + ); + fprintf (stdout, " %c%c", + 'a', + rtems_capture_task_flags (tcb) & RTEMS_CAPTURE_TRACED ? 't' : '-'); if ((floor > ceiling) && (ceiling > priority)) fprintf (stdout, "--"); else fprintf (stdout, "%c%c", - rtems_capture_task_control (tasks[i]) ? - (rtems_capture_task_control_flags (tasks[i]) & + rtems_capture_task_control (tcb) ? + (rtems_capture_task_control_flags (tcb) & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-', rtems_capture_watch_global_on () ? 'g' : '-'); fprintf (stdout, " "); - rtems_capture_cli_print_timestamp (rtems_capture_task_time (tasks[i])); fprintf (stdout, "\n"); } - if (count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS) + if (rtems_capture_cli_task_count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS) { - j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - count; + j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - rtems_capture_cli_task_count; while (j > 0) { fprintf (stdout, "\x1b[K\n"); @@ -471,7 +543,7 @@ rtems_capture_cli_task_load_thread (rtems_task_argument arg) } } - last_count = count; + last_count = rtems_capture_cli_task_count; cli_load_thread_active = 0; @@ -1415,42 +1487,23 @@ rtems_capture_cli_trace_records (int argc, rec = (rtems_capture_record_t*) ptr; if (csv) - fprintf (stdout, "%08" PRIxPTR ",%03" PRIu32 + fprintf (stdout, "%08" PRIu32 ",%03" PRIu32 ",%03" PRIu32 ",%04" PRIx32 ",%" PRId64 "\n", - (uintptr_t) rec->task, + rec->task_id, (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, (rec->events >> RTEMS_CAPTURE_EVENT_START), (uint64_t) rec->time); - else - { - uint64_t diff = 0; - uint32_t event; - int e; - - event = rec->events >> RTEMS_CAPTURE_EVENT_START; - - for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++) - { - if (event & 1) - { - rtems_capture_cli_print_timestamp (rec->time); - if (last_t) - diff = rec->time - last_t; - last_t = rec->time; - fprintf (stdout, " %9" PRId64 " ", diff); - rtems_monitor_dump_id (rtems_capture_task_id (rec->task)); - fprintf (stdout, " %c%c%c%c", - (char) (rec->task->name >> 24) & 0xff, - (char) (rec->task->name >> 16) & 0xff, - (char) (rec->task->name >> 8) & 0xff, - (char) (rec->task->name >> 0) & 0xff); - fprintf (stdout, " %3" PRId32 " %3" PRId32 " %s\n", - (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff, - (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff, - rtems_capture_event_text (e)); - } - event >>= 1; + else { + if ((rec->events >> RTEMS_CAPTURE_EVENT_START) == 0) + rtems_caputre_cli_print_record_task( rec ); + else { + uint64_t diff = 0; + if (last_t) + diff = rec->time - last_t; + last_t = rec->time; + + rtems_caputure_cli_print_record_std( rec, diff ); } } ptr += rec->size; |