[rtems commit] libmisc: Add top to cpuusage.
Jennifer Averett
Jennifer.Averett at OARcorp.com
Thu Oct 30 15:11:02 UTC 2014
My name and email are correct in git config.
> -----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
More information about the devel
mailing list