[rtems commit] libmisc: Add top to cpuusage.
Joel Sherrill
joel.sherrill at oarcorp.com
Thu Oct 30 17:11:11 UTC 2014
On 10/30/2014 12:06 PM, Jennifer Averett wrote:
> 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.
Just reformat it. :)
--joel
> 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
> _______________________________________________
> 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