Add 'getidle' CPU utilization measurement infrastructure

This commit is contained in:
David van Moolenbroek
2009-12-02 11:52:26 +00:00
parent be2087ecf9
commit fce9fd4b4e
22 changed files with 190 additions and 31 deletions

View File

@@ -8,7 +8,6 @@
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <minix/sysutil.h>
#include "../../proc.h"
#include "../../proto.h"
#include "../../vm.h"

View File

@@ -6,7 +6,6 @@
#include <minix/type.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/cpufeature.h>
#include <string.h>

View File

@@ -119,7 +119,6 @@ struct tss_s {
EXTERN struct tss_s tss;
_PROTOTYPE( void prot_init, (void) );
_PROTOTYPE( void idt_init, (void) );
_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege) );

View File

@@ -9,7 +9,6 @@
#include <ibm/bios.h>
#include <minix/portio.h>
#include <minix/u64.h>
#include <minix/sysutil.h>
#include <a.out.h>
#include "proto.h"

View File

@@ -118,6 +118,8 @@ PUBLIC int bsp_timer_int_handler(void)
{
unsigned ticks;
IDLE_STOP;
if(minix_panicing)
return 0;
@@ -228,6 +230,8 @@ PUBLIC int ap_timer_int_handler(void)
int expired = 0;
struct proc * p, * billp;
IDLE_STOP;
/* Update user and system accounting times. Charge the current process
* for user time. If the current process is not billable, that is, if a
* non-user process is running, charge the billable process for system

View File

@@ -45,6 +45,12 @@
#define lock reallock
#define unlock realunlock
#ifdef CONFIG_IDLE_TSC
#define IDLE_STOP if(idle_active) { read_tsc_64(&idle_stop); idle_active = 0; }
#else
#define IDLE_STOP
#endif
/* args to intr_init() */
#define INTS_ORIG 0 /* restore interrupts */
#define INTS_MINIX 1 /* initialize interrupts for minix */

View File

@@ -1,8 +1,6 @@
#ifndef GLO_H
#define GLO_H
#include <minix/sysutil.h>
/* Global variables used in the kernel. This file contains the declarations;
* storage space for the variables is allocated in table.c, because EXTERN is
* defined as extern unless the _TABLE definition is seen. We rely on the
@@ -66,6 +64,12 @@ EXTERN int verboseflags;
EXTERN int config_no_apic; /* optionaly turn off apic */
#endif
#ifdef CONFIG_IDLE_TSC
EXTERN u64_t idle_tsc;
EXTERN u64_t idle_stop;
EXTERN int idle_active;
#endif
/* VM */
EXTERN int vm_running;
EXTERN int catch_pagefaults;

View File

@@ -112,6 +112,8 @@ PUBLIC void irq_handle(int irq)
{
irq_hook_t * hook;
IDLE_STOP;
/* here we need not to get this IRQ until all the handlers had a say */
hw_intr_mask(irq);
hook = irq_handlers[irq];

View File

@@ -5,6 +5,8 @@
#define CONFIG_APIC
/* boot verbose */
#define CONFIG_BOOT_VERBOSE
/* measure cumulative idle timestamp counter ticks */
#undef CONFIG_IDLE_TSC
/* This is the master header for the kernel. It includes some other files
* and defines the principal constants.
@@ -20,6 +22,7 @@
#include <minix/const.h> /* MINIX specific constants */
#include <minix/type.h> /* MINIX specific types, e.g. message */
#include <minix/ipc.h> /* MINIX run-time system */
#include <minix/sysutil.h> /* MINIX utility library functions */
#include <timers.h> /* watchdog timer management */
#include <errno.h> /* return codes and error numbers */

View File

@@ -16,6 +16,7 @@
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
#include "proc.h"
#include "debug.h"
#include "clock.h"
@@ -189,6 +190,10 @@ PUBLIC void main()
#endif /* SPROFILE */
cprof_procs_no = 0; /* init nr of hash table slots used */
#ifdef CONFIG_IDLE_TSC
idle_tsc = cvu64(0);
#endif
vm_running = 0;
krandom.random_sources = RANDOM_SOURCES;
krandom.random_elements = RANDOM_ELEMENTS;

View File

@@ -40,6 +40,7 @@
#include <signal.h>
#include <minix/portio.h>
#include <minix/u64.h>
#include <minix/syslib.h>
#include "debug.h"
#include "kernel.h"
@@ -50,6 +51,7 @@
* other parts of the kernel through lock_...(). The lock temporarily disables
* interrupts to prevent race conditions.
*/
FORWARD _PROTOTYPE( void idle, (void));
FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst_e,
message *m_ptr, int flags));
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
@@ -123,6 +125,35 @@ PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst)
NOREC_RETURN(queuemess, OK);
}
/*===========================================================================*
* idle *
*===========================================================================*/
PRIVATE void idle()
{
/* This function is called whenever there is no work to do.
* Halt the CPU, and measure how many timestamp counter ticks are
* spent not doing anything. This allows test setups to measure
* the CPU utiliziation of certain workloads with high precision.
*/
#ifdef CONFIG_IDLE_TSC
u64_t idle_start;
read_tsc_64(&idle_start);
idle_active = 1;
#endif
halt_cpu();
#ifdef CONFIG_IDLE_TSC
if (idle_active) {
IDLE_STOP;
printf("Kernel: idle active after resuming CPU\n");
}
idle_tsc = add64(idle_tsc, sub64(idle_stop, idle_start));
#endif
}
/*===========================================================================*
* schedcheck *
*===========================================================================*/
@@ -166,7 +197,7 @@ not_runnable_pick_new:
proc_ptr = proc_addr(IDLE);
if (priv(proc_ptr)->s_flags & BILLABLE)
bill_ptr = proc_ptr;
halt_cpu();
idle();
}
check_misc_flags:

View File

@@ -19,6 +19,7 @@ _PROTOTYPE( void reset_timer, (struct timer *tp) );
_PROTOTYPE( void ser_dump_proc, (void) );
/* main.c */
_PROTOTYPE( void main, (void) );
_PROTOTYPE( void prepare_shutdown, (int how) );
_PROTOTYPE( void minix_shutdown, (struct timer *tp) );
@@ -102,6 +103,7 @@ _PROTOTYPE( void stop_profile_clock, (void) );
#endif
/* functions defined in architecture-dependent files. */
_PROTOTYPE( void prot_init, (void) );
_PROTOTYPE( phys_bytes phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) );
_PROTOTYPE( void phys_copy_fault, (void));

View File

@@ -141,18 +141,26 @@ register message *m_ptr; /* pointer to request message */
break;
}
#endif
case GET_IRQACTIDS: {
length = sizeof(irq_actids);
src_vir = (vir_bytes) irq_actids;
break;
}
case GET_PRIVID:
case GET_PRIVID: {
if (!isokendpt(m_ptr->I_VAL_LEN2_E, &proc_nr))
return EINVAL;
return proc_addr(proc_nr)->p_priv->s_id;
}
case GET_IDLETSC: {
#ifdef CONFIG_IDLE_TSC
length = sizeof(idle_tsc);
src_vir = (vir_bytes) &idle_tsc;
break;
#else
kprintf("do_getinfo: kernel not compiled with CONFIG_IDLE_TSC\n");
return(EINVAL);
#endif
}
default:
kprintf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
return(EINVAL);

View File

@@ -11,7 +11,6 @@
#include <signal.h>
#include <string.h>
#include <minix/sysutil.h>
#include <minix/sys_config.h>
/*===========================================================================*