[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