[rtems commit] libmisc: Add top to cpuusage.
Joel Sherrill
joel.sherrill at oarcorp.com
Thu Oct 30 15:03:22 UTC 2014
On 10/30/2014 9:55 AM, Gedare Bloom wrote:
> The email address came from VC, so it is a problem in the commit setup I guess.
OK. I will help her double check. Working on multiple machines,
I periodically find one that is wrong for myself. :(
--joel
> On Thu, Oct 30, 2014 at 10:55 AM, Joel Sherrill
> <joel.sherrill at oarcorp.com> wrote:
>> FWIW she is jennifer.averett at rtems.org not jennifer at .
>>
>> --joel
>>
>> On 10/30/2014 9:53 AM, Gedare Bloom wrote:
>>> I missed reviewing this patch earlier, but there are some style
>>> problems with it, please fix them on the head.
>>>
>>> On Tue, Oct 28, 2014 at 11:17 AM, Jennifer Averett <jennifer at rtems.org> wrote:
>>>> Module: rtems
>>>> Branch: master
>>>> Commit: 6031da438d219c6ec5d9d48f1df2aef91710cce3
>>>> Changeset: http://git.rtems.org/rtems/commit/?id=6031da438d219c6ec5d9d48f1df2aef91710cce3
>>>>
>>>> Author: Jennifer Averett <jennifer.averett at oarcorp.com>
>>>> Date: Mon Sep 29 10:20:27 2014 -0500
>>>>
>>>> libmisc: Add top to cpuusage.
>>>>
>>>> ---
>>>>
>>>> cpukit/libmisc/Makefile.am | 2 +-
>>>> cpukit/libmisc/cpuuse/cpuusagetop.c | 337 +++++++++++++++++++++++++++++++++++
>>>> cpukit/libmisc/cpuuse/cpuuse.h | 19 ++
>>>> 3 files changed, 357 insertions(+), 1 deletions(-)
>>>>
>>>> diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
>>>> index 2f41ffa..d26c484 100644
>>>> --- a/cpukit/libmisc/Makefile.am
>>>> +++ b/cpukit/libmisc/Makefile.am
>>>> @@ -27,7 +27,7 @@ EXTRA_DIST += cpuuse/README
>>>>
>>>> noinst_LIBRARIES += libcpuuse.a
>>>> libcpuuse_a_SOURCES = cpuuse/cpuusagereport.c cpuuse/cpuusagereset.c \
>>>> - cpuuse/cpuuse.h cpuuse/cpuusagedata.c
>>>> + cpuuse/cpuuse.h cpuuse/cpuusagedata.c cpuuse/cpuusagetop.c
>>>>
>>>> ## devnull
>>>> noinst_LIBRARIES += libdevnull.a
>>>> diff --git a/cpukit/libmisc/cpuuse/cpuusagetop.c b/cpukit/libmisc/cpuuse/cpuusagetop.c
>>>> new file mode 100644
>>>> index 0000000..7e7348a
>>>> --- /dev/null
>>>> +++ b/cpukit/libmisc/cpuuse/cpuusagetop.c
>>>> @@ -0,0 +1,337 @@
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * @brief CPU Usage Top
>>>> + * @ingroup libmisc_cpuuse CPU Usage
>>>> + */
>>>> +
>>>> +/*
>>>> + * 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 or at
>>>> + * http://www.rtems.org/license/LICENSE.
>>>> + */
>>>> +
>>>> +#ifdef HAVE_CONFIG_H
>>>> +#include "config.h"
>>>> +#endif
>>>> +
>>>> +#include <string.h>
>>>> +#include <stdlib.h>
>>>> +#include <stdio.h>
>>>> +#include <ctype.h>
>>>> +#include <inttypes.h>
>>>> +
>>>> +#include <rtems/cpuuse.h>
>>>> +#include <rtems/score/objectimpl.h>
>>>> +#include <rtems/score/threadimpl.h>
>>>> +#include <rtems/score/todimpl.h>
>>>> +#include <rtems/score/watchdogimpl.h>
>>>> +
>>>> +
>>>> +/*
>>>> + * Common variable to sync the load monitor task.
>>>> + */
>>>> +static volatile int rtems_cpuusage_top_thread_active;
>>>> +
>>>> +
>>> remove multiple blank lines
>>>
>>>> +typedef struct {
>>>> + void *context;
>>>> + rtems_printk_plugin_t print;
>>>> +}rtems_cpu_usage_plugin_t;
>>>> +
>>>> +#define RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS (20)
>>>> +
>>>> +/*
>>>> + * rtems_cpuusage_top_thread
>>>> + *
>>>> + * DESCRIPTION:
>>>> + *
>>>> + * This function displays the load of the tasks on an ANSI terminal.
>>>> + *
>>> Get rid of "DESCRIPTION", prefer to use minimalist comment style on
>>> static functions.
>>>
>>>> + */
>>>> +
>>>> +static void
>>>> +rtems_cpuusage_top_thread (rtems_task_argument arg)
>>>> +{
>>>> + uint32_t api_index;
>>>> + Thread_Control* the_thread;
>>>> + int i;
>>>> + int j;
>>>> + int k;
>>>> + Objects_Information* information;
>>>> + char name[13];
>>>> + int task_count = 0;
>>>> + uint32_t seconds, nanoseconds;
>>>> + rtems_cpu_usage_plugin_t* plugin = (rtems_cpu_usage_plugin_t*)arg;
>>>> + Thread_Control* load_tasks[RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS + 1];
>>>> + unsigned long long load[RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS + 1];
>>>> +
>>>> + while (true)
>>>> + {
>>> Opening brace should go on whille() line.
>>>
>>>> + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
>>>> + Timestamp_Control uptime, total, ran, uptime_at_last_reset;
>>>> + #else
>>>> + uint32_t total_units = 0;
>>>> + #endif
>>>> +
>>>> + rtems_cpuusage_top_thread_active = 1;
>>>> +
>>>> + memset (load_tasks, 0, sizeof (load_tasks));
>>>> + memset (load, 0, sizeof (load));
>>>> +
>>>> + /*
>>>> + * Iterate over the tasks and sort the highest load tasks
>>>> + * into our local arrays. We only handle a limited number of
>>>> + * tasks.
>>>> + */
>>>> + for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
>>>> + #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
>>>> + if ( !_Objects_Information_table[ api_index ] )
>>>> + continue;
>>>> + #endif
>>>> +
>>>> + information = _Objects_Information_table[ api_index ][ 1 ];
>>>> + if ( information ) {
>>>> + for ( k=1 ; k <= information->maximum ; k++ ) {
>>> I prefer that nested iterators should be used in increasing order, e.g. i first.
>>>
>>>> + the_thread = (Thread_Control *)information->local_table[ k ];
>>>> + if ( the_thread ) {
>>>> +
>>> No blank space after the opening brace.
>>>
>>>> + Thread_CPU_usage_t l = the_thread->cpu_time_used;
>>> Avoid using l and I as variable names.They're hard to differentiate
>>> from each other and from the digit 1. This should be a more useful
>>> variable name anyway. A one-letter variable should really only be used
>>> for iterators. We ought to have a rule about this if we don't.
>>>
>>>> +
>>>> + /*
>>>> + * When not using nanosecond CPU usage resolution, we have to count
>>>> + * the number of "ticks" we gave credit for to give the user a rough
>>>> + * guideline as to what each number means proportionally.
>>>> + */
>>>> + #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__
>>>> + total_units += l;
>>>> + #endif
>>>> +
>>>> + /* Count the number of tasks and sort this load value */
>>>> + task_count++;
>>>> + for (i = 0; i < RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS; i++) {
>>>> + if (load_tasks[i]) {
>>>> + if ((l == 0) || (l < load[i]))
>>>> + continue;
>>>> + for (j = (RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS - 1); j >= i; j--){
>>>> + load_tasks[j + 1] = load_tasks[j];
>>>> + load[j + 1] = load[j];
>>>> + }
>>>> + }
>>>> + load_tasks[i] = the_thread;
>>>> + load[i] = l;
>>>> + break;
>>>> + }
>>>> + }
>>>> + }
>>>> + }
>>>> + }
>>>> +
>>>> + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
>>>> + _Timestamp_Set_to_zero( &total );
>>>> + uptime_at_last_reset = CPU_usage_Uptime_at_last_reset;
>>>> + #endif
>>>> +
>>>> + _TOD_Get_uptime( &uptime );
>>>> + seconds = _Timestamp_Get_seconds( &uptime );
>>>> + nanoseconds = _Timestamp_Get_nanoseconds( &uptime ) /
>>>> + TOD_NANOSECONDS_PER_MICROSECOND;
>>>> + (*plugin->print)(plugin->context, "\x1b[H\x1b[J Press ENTER to exit.\n\n");
>>>> + (*plugin->print)(plugin->context, "uptime: ");
>>>> + (*plugin->print)(plugin->context,
>>>> + "%7" PRIu32 ".%06" PRIu32 "\n", seconds, nanoseconds
>>>> + );
>>>> +
>>>> + (*plugin->print)(
>>>> + plugin->context,
>>>> + "-------------------------------------------------------------------------------\n"
>>>> + " CPU USAGE BY THREAD\n"
>>>> + "------------+---------------------+---------------+---------------+------------\n"
>>>> + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
>>>> + " ID | NAME | RPRI | CPRI | SECONDS | PERCENT\n"
>>>> + #else
>>>> + " ID | NAME | RPRI | CPRI | TICKS | PERCENT\n"
>>>> + #endif
>>>> + "------------+---------------------+---------------+---------------+------------\n"
>>>> + );
>>>> +
>>>> + for (i = 0; i < RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS; i++)
>>>> + {
>>>> +
>>> Fix style here.
>>>
>>>> + if (!load_tasks[i])
>>>> + break;
>>>> +
>>>> + /*
>>>> + * If this is the currently executing thread, account for time
>>>> + * since the last context switch.
>>>> + */
>>>> + the_thread = load_tasks[i];
>>>> +
>>>> + rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
>>>> + (*plugin->print)(
>>>> + plugin->context,
>>>> + " 0x%08" PRIx32 " | %-19s | %3" PRId32 " | %3" PRId32 " |",
>>>> + the_thread->Object.id,
>>>> + name,
>>>> + the_thread->real_priority,
>>>> + the_thread->current_priority
>>>> + );
>>>> +
>>>> + #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
>>>> + {
>>> I don't know how to feel about artifically adding scoped blocks.
>>> Anyone else weigh in?
>>>
>>>> + Timestamp_Control last;
>>>> + uint32_t ival, fval;
>>>> +
>>>> + /*
>>>> + * If this is the currently executing thread, account for time
>>>> + * since the last context switch.
>>>> + */
>>>> + ran = load[i];
>>>> + if ( _Thread_Get_time_of_last_context_switch( the_thread, &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 );
>>>> +
>>>> + /*
>>>> + * Print the information
>>>> + */
>>>> +
>>>> + seconds = _Timestamp_Get_seconds( &ran );
>>>> + nanoseconds = _Timestamp_Get_nanoseconds( &ran ) /
>>>> + TOD_NANOSECONDS_PER_MICROSECOND;
>>>> + (*plugin->print)( plugin->context,
>>>> + "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
>>>> + seconds, nanoseconds,
>>>> + ival, fval
>>>> + );
>>>> + }
>>>> + #else
>>>> + if (total_units) {
>>>> + uint64_t ival_64;
>>>> +
>>>> + ival_64 = load[i];
>>>> + ival_64 *= 100000;
>>>> + ival = ival_64 / total_units;
>>>> + } else {
>>>> + ival = 0;
>>>> + }
>>>> +
>>>> + fval = ival % 1000;
>>>> + ival /= 1000;
>>>> + (*plugin->print)( plugin->context,
>>>> + "%14" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
>>>> + load[i],
>>>> + ival,
>>>> + fval
>>>> + );
>>>> + #endif
>>>> + }
>>>> +
>>>> + if (task_count < RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS)
>>>> + {
>>>> + j = RTEMS_CPUUSAGE_TOP_MAX_LOAD_TASKS - task_count;
>>>> + while (j > 0)
>>>> + {
>>>> + (*plugin->print)( plugin->context, "\x1b[K\n");
>>>> + j--;
>>>> + }
>>>> + }
>>>> +
>>>> + rtems_cpuusage_top_thread_active = 0;
>>>> +
>>>> + rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (5000000));
>>>> + }
>>>> +}
>>>> +
>>>> +void rtems_cpu_usage_top_with_plugin(
>>>> + void *context,
>>>> + rtems_printk_plugin_t print
>>>> +)
>>>> +{
>>>> + rtems_status_code sc;
>>>> + rtems_task_priority priority;
>>>> + rtems_name name;
>>>> + rtems_id id;
>>>> + rtems_cpu_usage_plugin_t plugin;
>>>> +
>>>> + if ( !print )
>>>> + return;
>>>> +
>>>> + plugin.context = context;
>>>> + plugin.print = print;
>>>> +
>>>> + sc = rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
>>>> +
>>>> + if (sc != RTEMS_SUCCESSFUL)
>>>> + {
>>>> + (*print)(
>>>> + context,
>>>> + "error: cannot obtain the current priority: %s\n",
>>>> + rtems_status_text (sc)
>>>> + );
>>>> + return;
>>>> + }
>>>> +
>>>> + name = rtems_build_name('C', 'P', 'l', 't');
>>>> +
>>>> + sc = rtems_task_create (name, priority, 4 * 1024,
>>>> + RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
>>>> + RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
>>>> + &id);
>>>> +
>>>> + if (sc != RTEMS_SUCCESSFUL)
>>>> + {
>>>> + (*print)(
>>>> + context,
>>>> + "error: cannot create helper thread: %s\n",
>>>> + rtems_status_text (sc)
>>>> + );
>>>> + return;
>>>> + }
>>>> +
>>>> + sc = rtems_task_start (
>>>> + id, rtems_cpuusage_top_thread, (rtems_task_argument)&plugin
>>>> + );
>>>> + if (sc != RTEMS_SUCCESSFUL)
>>>> + {
>>>> + (*print)(
>>>> + context,
>>>> + "error: cannot start helper thread: %s\n",
>>>> + rtems_status_text (sc)
>>>> + );
>>>> + rtems_task_delete (id);
>>>> + return;
>>>> + }
>>>> +
>>>> + for (;;)
>>>> + {
>>>> + int c = getchar ();
>>>> +
>>>> + if ((c == '\r') || (c == '\n'))
>>>> + {
>>>> + int loops = 20;
>>>> +
>>>> + while (loops && rtems_cpuusage_top_thread_active)
>>>> + rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (100000));
>>>> +
>>>> + rtems_task_delete (id);
>>>> +
>>>> + (*print)(context, "load monitoring stopped.\n");
>>>> + return;
>>>> + }
>>>> + }
>>>> +}
>>>> +
>>>> +void rtems_cpu_usage_top( void )
>>>> +{
>>>> + rtems_cpu_usage_top_with_plugin( NULL, printk_plugin );
>>>> +}
>>>> diff --git a/cpukit/libmisc/cpuuse/cpuuse.h b/cpukit/libmisc/cpuuse/cpuuse.h
>>>> index 1aee275..662d905 100644
>>>> --- a/cpukit/libmisc/cpuuse/cpuuse.h
>>>> +++ b/cpukit/libmisc/cpuuse/cpuuse.h
>>>> @@ -63,6 +63,25 @@ void rtems_cpu_usage_report_with_plugin(
>>>> void rtems_cpu_usage_report( void );
>>>>
>>>> /**
>>>> + * @brief CPU usage Top plugin
>>>> + *
>>>> + * Report CPU Usage in top format to
>>>> + * to a print plugin.
>>>> + */
>>>> +void rtems_cpu_usage_top_with_plugin(
>>>> + void *context,
>>>> + rtems_printk_plugin_t print
>>>> +);
>>>> +
>>>> +/**
>>>> + * @brief CPU usage top.
>>>> + *
>>>> + * CPU Usage top
>>>> + */
>>>> +
>>>> +void rtems_cpu_usage_top( void );
>>>> +
>>>> +/**
>>>> * @brief Reset CPU usage.
>>>> *
>>>> * CPU Usage Reporter
>>>>
>>>> _______________________________________________
>>>> vc mailing list
>>>> vc at rtems.org
>>>> http://lists.rtems.org/mailman/listinfo/vc
>>> _______________________________________________
>>> devel mailing list
>>> devel at rtems.org
>>> http://lists.rtems.org/mailman/listinfo/devel
>> --
>> Joel Sherrill, Ph.D. Director of Research & Development
>> joel.sherrill at OARcorp.com On-Line Applications Research
>> Ask me about RTEMS: a free RTOS Huntsville AL 35805
>> Support Available (256) 722-9985
>>
--
Joel Sherrill, Ph.D. Director of Research & Development
joel.sherrill at OARcorp.com On-Line Applications Research
Ask me about RTEMS: a free RTOS Huntsville AL 35805
Support Available (256) 722-9985
More information about the devel
mailing list