Idle meter (orig: Re: Network and CPU usage)

From: sampsa@staff.netsonic.fi
Date: Sun Jun 11 2000 - 09:51:21 EST


On Sun, 11 Jun 2000 bof@oknodo.bof.de wrote:

> > > I don't think that you can say that "networking / firewalling runs in the
> > > context of the idle task" - as far as I know it runs in the context of
> > > whatever task is active when the interrupt hits.
> >
> > You're saying it's using the context of currently running task, um. If it
> > runs then on my new userspace idle task, does that give me any more
> > information about running low on resources?
>
> Yes; your user level idle task won't make progress during the microseconds
> when it is interrupted, and kernel code is running in it's context.
> What you do is count the revolutions in your endless loop, and take that
> as a measure of "spare time".

Hello,

I didn't found good enough time keeping for user level, so I implemented
a kernel level task that takes use of idle time, as far as I understood,
the mdelay() takes use of udelay() but is more precise. I just am not sure do
interrupts affect these, if they do, this code is utterly useless.

People, correct if I am wrong, please. Any advices for improving this
piece of code would be nice. I am going to use it on production router
calculate true spare time of CPU.

 - Sampsa Ranta
   sampsa@netsonic.fi

--- idle.c
/*
 * Alternative idle task by Sampsa Ranta
 * Use freely, I take no responsiblity, anyway..
 */

#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/smp_lock.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/io.h>

#include <linux/delay.h>

static int myidle_pid = 0; /* PID of myidle */
static int myidle_running = 0;

static unsigned long my_cycles;

static int myidle_get_info(char *buffer, char **start, off_t offset, int length)
{
  int len = 0;
  len += sprintf(buffer+len,"Idle counter: %d\n",my_cycles);
  return len;
}

static int myidle_thread(void *unused)
{
#ifdef TEST_IDLE
  static int count;
#endif

  /*
    MOD_INC_USE_COUNT;
  */
  myidle_running = 1;
  
  lock_kernel();
  
  /*
   * This thread doesn't need any user-level access,
   * so get rid of all our resources
   */
  exit_files(current); /* daemonize doesn't do exit_files */
  daemonize();
  
  /* Setup a nice name */
  strcpy(current->comm, "myidled");

  /* We're the idle process now! */
  current->priority=-19;

  proc_net_create("myidled", 0, myidle_get_info);

  set_task_state(current, TASK_INTERRUPTIBLE);

#ifdef TEST_IDLE
  // 30 seconds test run
    count = 30 * 1000;
#endif

  /* Send me a signal to get me die (for debugging) */
#ifdef TEST_IDLE
  while (!signal_pending(current) && --count ) {
#else
  while (!signal_pending(current)) {
#endif
    mdelay(1);
    my_cycles++;
    schedule_timeout(0);
  }

#ifdef TEST_IDLE
  schedule();
  current->state = TASK_RUNNING;
#endif

  proc_net_remove("myidled");

  myidle_running = 0;
  /*
    MOD_DEC_USE_COUNT;
  */
  return 0;
}

/*
 * This should be a separate module.
 */

int myidle_init_module(void)
{
        int pid;

        pid = kernel_thread(myidle_thread, NULL,
                CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
        if (pid >= 0) {
                myidle_pid = pid;

                return 0;
        }

        /* Fall through if kernel_thread failed */

        return -1;
}

void myidle_cleanup_module(void)
{
        int ret;

        /* Kill the thread */
        ret = kill_proc(myidle_pid, SIGTERM, 1);
        if (!ret) {
                /* Wait 10 seconds */
                int count = 10 * 100;

                while (myidle_running && --count) {
                        current->state = TASK_INTERRUPTIBLE;
                        schedule_timeout(1);
                }

                // if (!count)
                // err("giving up on killing myidle");
        }
}

module_init(myidle_init_module);
module_exit(myidle_cleanup_module);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:23 EST