[rtems commit] libmisc: Add top to cpuusage.
Gedare Bloom
gedare at rtems.org
Thu Oct 30 15:07:53 UTC 2014
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=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