[rtems commit] libmisc: Add top to cpuusage.

Jennifer Averett Jennifer.Averett at OARcorp.com
Thu Oct 30 17:06:59 UTC 2014


Addressing all the comments.  About the scoped blocks I used the style
that existed in cpuusage already.  That section of code is modified code
from  rtems_cpu_usage_report_with_plugin.

Jennifer

> -----Original Message-----
> From: devel [mailto:devel-bounces at rtems.org] On Behalf Of Gedare Bloom
> Sent: Thursday, October 30, 2014 9:54 AM
> To: Jennifer Averett
> Cc: rtems-devel at rtems.org
> Subject: Re: [rtems commit] libmisc: Add top to cpuusage.
>
> 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=6031da438d219c6ec5d9d48f1df2aef9
> > 1710cce3
> >
> > 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


More information about the devel mailing list