public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* Re: [ECOS] load monitoring (on an ARM)
@ 2000-02-10 19:31 Travis Furrer
  2000-02-11  0:24 ` Andrew Lunn
  0 siblings, 1 reply; 4+ messages in thread
From: Travis Furrer @ 2000-02-10 19:31 UTC (permalink / raw)
  To: ecos-discuss

Thanks Andrew for the cpuload code!  It seems to work quite
nicely.

However, one pitfall of using idle_thread_loops as the indicator
of CPU load is that the code in HAL_IDLE_THREAD_ACTION can
interfere.  For example, in my case I need to use
HAL_IDLE_THREAD_ACTION to actually put the processor into its
idle mode (to conserve energy).  This invalidates the implicit
assumption that each pass through the body of the idle loop
corresponds to roughly the same amount of time.  So in this case
the idle_thread_loops counter is not as useful as an indicator of
CPU idle time.

Can anyone suggest a workaround, or think of an alternative
implementation for load monitoring for cases like mine?

Thanks,
Travis


andrew.lunn@ascom.ch said:
> This is not as clean as it should be but ....
>
>         Andrew
>
.
.
.

______________________________________________
FREE Personalized Email at Mail.com
Sign up at http://www.mail.com?sr=mc.mk.mcm.tag001

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [ECOS] load monitoring (on an ARM)
  2000-02-10 19:31 [ECOS] load monitoring (on an ARM) Travis Furrer
@ 2000-02-11  0:24 ` Andrew Lunn
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Lunn @ 2000-02-11  0:24 UTC (permalink / raw)
  To: Travis Furrer; +Cc: ecos-discuss

> Thanks Andrew for the cpuload code!  It seems to work quite
> nicely.

Good.
 
> However, one pitfall of using idle_thread_loops as the indicator
> of CPU load is that the code in HAL_IDLE_THREAD_ACTION can
> interfere.

Yep. I thought about that when i designed to code and then ignored it
because my system is always plugged into the mains.

I think the only way out of the idle loop is via an interrupt.  I
assume you get your tick interrupts from a high speed clock. When you
go into idle mode read the high speed clock. In the interrupt
processing code add another read to the high speed clock. Subtract and
you have the time in idle mode.

        Andrew

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [ECOS] load monitoring (on an ARM)
  2000-02-09 15:43 Travis Furrer
@ 2000-02-10  0:15 ` Andrew Lunn
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Lunn @ 2000-02-10  0:15 UTC (permalink / raw)
  To: Travis Furrer; +Cc: ecos-discuss

This is not as clean as it should be but ....

        Andrew

____________________________

Andrew Lunn
Research Engineer
Phone +41 62 889 52 97
Fax +41 62 889 52 90
Andrew.Lunn@ascom.ch

Ascom Systec Ltd.
Applicable Research & Technology
Gewerbepark
CH-5506 Maegenwil
Switzerland

www.ascom.com/art


/* This files provides a simple CPU load meter. All loads are returned
   as a percentage, ie 0-100. This is only a rough measure. */

/* This code is Copywrite ASCOM SYSTEC, Gewerberpark, Magenwil,
   Switzerland, 1999, 2000 etc. Fee free to use, modify, hack, but not
   sell for money. ASCOM Takes no responsiability for this code at all
   etc. 
#include <std/disclaimer.h>
*/

#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_arch.h>  /* Needed for the HAL_IDLE_THREAD_ACTIOM */
#include <assert.h>
#include "cpu_load.h"

/* Here we run the idle thread as a high priority thread for 0.1
   second and see how much the counter in the idle loop is
   incremented. This will only work is there are no other threads
   running at priority 1 and 2 */

static cyg_thread thread;
extern cyg_uint32 idle_thread_loops;
char idle_stack[CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE];

// -------------------------------------------------------------------------
// Idle thread code. This is a cut and paste from thread.cxx. Some day i will
// work out how to call the real idle thread 

void
idle_thread_main( CYG_ADDRESS data )
{
  //    CYG_REPORT_FUNCTION();

    for(;;)
    {
        idle_thread_loops++;

        HAL_IDLE_THREAD_ACTION(idle_thread_loops);

#if 0
        // For testing, it is useful to be able to fake
        // clock interrupts in the idle thread.
        
        Cyg_Clock::real_time_clock->tick();
#endif
#ifdef CYGIMP_IDLE_THREAD_YIELD
        // In single priority and non-preemptive systems,
        // the idle thread should yield repeatedly to
        // other threads.
        Cyg_Thread::yield();
#endif
    }
}
// -------------------------------------------------------------------------

/* We are playing ping-pong with the cpuload_calibrate function and
   the idle thread. First cpuload_calibrate runs. Next the idle
   thread, then this alarm function and then back to the
   cpuload_calibrate function. Well thats the theory */

void static 
alarm_func(cyg_handle_t alarm,cyg_addrword_t data) { 
  cyg_handle_t idleH = (cyg_handle_t) data;
  cyg_thread_suspend(idleH); 
}

void 
cpuload_calibrate(cyg_uint32  *calibration) {
  cyg_handle_t counter;
  cyg_alarm alarm_s;
  cyg_handle_t alarmH;
  cyg_uint32 idle_loops_start;  
  cyg_handle_t idleH;
  cyg_priority_t old_priority;

  CYG_ASSERT(idleH != cyg_thread_self(),"Scheduler is broken!");

  cyg_thread_create(1,
		    idle_thread_main,
		    0,
		    "Calibration idle thread",
		    idle_stack,
		    CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE,
		    &idleH,
		    &thread);

  CYG_ASSERT(idleH != cyg_thread_self(),"Scheduler is broken!");

  cyg_clock_to_counter(cyg_real_time_clock(),&counter);
  cyg_alarm_create(counter,alarm_func,(cyg_addrword_t)idleH,&alarmH,&alarm_s);
  
  cyg_alarm_initialize(alarmH,cyg_current_time()+10,0);
  cyg_alarm_enable(alarmH);
  
  idle_loops_start = idle_thread_loops;

  /* Dont be decieved, remember this is a multithreaded system ! */
  CYG_ASSERT(idleH != cyg_thread_self(),"Scheduler is broken!");
  
  old_priority = cyg_thread_get_priority(cyg_thread_self());
  cyg_thread_set_priority(cyg_thread_self(),2);
  cyg_thread_resume(idleH);
  cyg_thread_set_priority(cyg_thread_self(),old_priority);

  *calibration = idle_thread_loops - idle_loops_start;
  cyg_alarm_delete(alarmH);
  CYG_ASSERT(idleH != cyg_thread_self(),"Scheduler is broken!");
  cyg_thread_kill(idleH);
}

  static uint32 last_time = 0;
  static int last_frame_count =0;
  static int count =0;

static void 
cpuload_alarm_func(cyg_handle_t alarm,cyg_addrword_t data) { 
  cpuload_t * cpuload = (cpuload_t *)data;
  cyg_uint32 idle_loops_now = idle_thread_loops;
  cyg_uint32 idle_loops;
  cyg_uint32 load;

  if (idle_loops_now >= cpuload->last_idle_loops) {
    idle_loops = idle_loops_now - cpuload->last_idle_loops;
  } else {
    idle_loops = ~0 - (cpuload->last_idle_loops - idle_loops_now);
  }
  
  /* We need 64 bit arithmatic to prevent wrap around */ 
  
  load = (cyg_uint32) (((cyg_uint64) idle_loops * (cyg_uint64)100) / 
		       (cyg_uint64)cpuload->calibration);
  if (load > 100) {
    load = 100;
  }
  load = 100 - load;
  
  cpuload->average_point1s = load;
  cpuload->average_1s = load + ((cpuload->average_1s * 90)/100);
  cpuload->average_10s = load + ((cpuload->average_10s * 99)/100);
  cpuload->life++;
  cpuload->last_idle_loops = idle_loops_now;
  
}


void 
cpuload_create(cpuload_t *cpuload,
	      cyg_uint32 calibration, 
	      cyg_handle_t *handle) 
{
  cyg_handle_t counter;

  cpuload->average_point1s = 0;
  cpuload->average_1s = 0;
  cpuload->average_10s = 0;
  cpuload->calibration = calibration;
  cpuload->last_idle_loops = idle_thread_loops;
  cyg_clock_to_counter(cyg_real_time_clock(),&counter);
  cyg_alarm_create(counter,
		   cpuload_alarm_func,
		   (cyg_addrword_t)cpuload,
		   &cpuload->alarmH,
		   &cpuload->alarm_s);

  cyg_alarm_initialize(cpuload->alarmH,cyg_current_time()+10,10);
  cyg_alarm_enable(cpuload->alarmH);
    
  *handle = (cyg_handle_t) cpuload;
}

void 
cpuload_delete(cyg_handle_t handle) {
  cpuload_t * cpuload = (cpuload_t *) handle;

  cyg_alarm_delete(cpuload->alarmH);
}  

void
cpuload_get(cyg_handle_t handle,
	    cyg_uint32 *average_point1s, 	    
	    cyg_uint32 *average_1s, 	    
	    cyg_uint32 *average_10s) {

  cpuload_t * cpuload = (cpuload_t *) handle;
  *average_point1s = cpuload->average_point1s;
  *average_1s = cpuload->average_1s/10;
  *average_10s = cpuload->average_10s/100;
}

------------------------
* cpuload.h - functions that give a rough estimate of the cpu load. */
#ifndef CPU_LOAD_H
#define CPU_LOAD_H

#include <cyg/kernel/kapi.h>

typedef struct cpuload_s {
  cyg_alarm alarm_s;
  cyg_handle_t alarmH;
  cyg_uint32 last_idle_loops;
  cyg_uint32 average_point1s;
  cyg_uint32 average_1s;
  cyg_uint32 average_10s;
  cyg_uint32 calibration;
  cyg_uint32 life;
} cpuload_t;

void cpuload_calibrate(cyg_uint32  *calibration);
void cpuload_create(cpuload_t *cpuload,
                    cyg_uint32 colibrate,
                    cyg_handle_t *handle);
void cpuload_delete(cyg_handle_t handle);
void cpuload_get(cyg_handle_t handle,
                 cyg_uint32 *average_point1s,
                 cyg_uint32 *average_1s,
                 cyg_uint32 *average_10s);

#endif /* CPU_LOAD_H */








^ permalink raw reply	[flat|nested] 4+ messages in thread

* [ECOS] load monitoring (on an ARM)
@ 2000-02-09 15:43 Travis Furrer
  2000-02-10  0:15 ` Andrew Lunn
  0 siblings, 1 reply; 4+ messages in thread
From: Travis Furrer @ 2000-02-09 15:43 UTC (permalink / raw)
  To: ecos-discuss

My eCos application needs to know how much time is spent
in the eCos idle thread (i.e. CPU idle time).  Can someone
recommend a good way to implement this? (on an ARM platform)

There are actually two issues:

1. how to monitor the idle time
(i.e. modify idle thread action?)

2. how to make this information available to the app
(i.e. add a function to the kernel API somewhere?)

Thank you,
Travis

______________________________________________
FREE Personalized Email at Mail.com
Sign up at http://www.mail.com?sr=mc.mk.mcm.tag001

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2000-02-11  0:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-02-10 19:31 [ECOS] load monitoring (on an ARM) Travis Furrer
2000-02-11  0:24 ` Andrew Lunn
  -- strict thread matches above, loose matches on Subject: below --
2000-02-09 15:43 Travis Furrer
2000-02-10  0:15 ` Andrew Lunn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).