[rtems commit] libmisc: Add top to cpuusage.
Joel Sherrill
joel.sherrill at oarcorp.com
Thu Oct 30 15:12:27 UTC 2014
On 10/30/2014 10:11 AM, Jennifer Averett wrote:
> My name and email are correct in git config.
And if it was converting git accounts into email addresses,
I would just be joel@ which would likely bounce as well.
-joel
>> -----Original Message-----
>> From: devel [mailto:devel-bounces at rtems.org] On Behalf Of Gedare Bloom
>> Sent: Thursday, October 30, 2014 10:08 AM
>> To: Joel Sherrill
>> Cc: Jennifer Averett; rtems-devel at rtems.org
>> Subject: Re: [rtems commit] libmisc: Add top to cpuusage.
>>
>> The problem may be a setup issue on git.rtems.org, where it converts from
>> user login to email, I think it might be doing something dumb like just taking
>> login-name @rtems.org
>>
>> On Thu, Oct 30, 2014 at 11:03 AM, Joel Sherrill <joel.sherrill at oarcorp.com>
>> wrote:
>>> 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=6031da438d219c6ec5d9d48f1df2
>>>>>>> aef91710cce3
>>>>>>>
>>>>>>> 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
>>>
>> _______________________________________________
>> 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
More information about the devel
mailing list