SMP - CPU local idle stub

- each CPU has its own pseudo idle process and its structure

- idle cycles accounting is agregated when exporting to userspace
This commit is contained in:
Tomas Hruby 2010-09-15 14:10:21 +00:00
parent fac5fbfdbf
commit 865e21b884
4 changed files with 65 additions and 4 deletions

View file

@ -223,7 +223,6 @@ PRIVATE void ap_finish_booting(void)
ap_boot_finished(cpu);
spinlock_unlock(&boot_lock);
for(;;);
/* finish processor initialisation. */
lapic_enable(cpu);

View file

@ -55,6 +55,7 @@ DECLARE_CPULOCAL_START
/* Process scheduling information and the kernel reentry count. */
DECLARE_CPULOCAL(struct proc *,proc_ptr);/* pointer to currently running process */
DECLARE_CPULOCAL(struct proc *,bill_ptr);/* process to bill for clock ticks */
DECLARE_CPULOCAL(struct proc ,idle_proc);/* stub for an idle process */
/*
* signal whether pagefault is already being handled to detect recursive

View file

@ -65,6 +65,42 @@ FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr,
FORWARD _PROTOTYPE( struct proc * pick_proc, (void));
FORWARD _PROTOTYPE( void enqueue_head, (struct proc *rp));
/* all idles share the same idle_priv structure */
PRIVATE struct priv idle_priv;
PRIVATE void set_idle_name(char * name, int n)
{
int i, c;
int p_z = 0;
/*
* P_NAME_LEN limits us to 3 characters for the idle task numer. 999
* should be enough though.
*/
if (n > 999)
n = 999;
name[0] = 'i';
name[1] = 'd';
name[2] = 'l';
name[3] = 'e';
for (i = 4, c = 100; c > 0; c /= 10) {
int digit;
digit = n / c;
n -= digit * c;
if (p_z || digit != 0 || c == 1) {
p_z = 1;
name[i++] = '0' + digit;
}
}
name[i] = '\0';
}
#define PICK_ANY 1
#define PICK_HIGHERONLY 2
@ -108,6 +144,14 @@ PUBLIC void proc_init(void)
sp->s_sig_mgr = NONE; /* clear signal managers */
sp->s_bak_sig_mgr = NONE;
}
idle_priv.s_flags = IDL_F;
/* initialize IDLE structures for every CPU */
for (i = 0; i < CONFIG_MAX_CPUS; i++) {
struct proc * ip = get_cpu_var_ptr(i, idle_proc);
ip->p_priv = &idle_priv;
set_idle_name(ip->p_name, i);
}
}
PRIVATE void switch_address_space_idle(void)
@ -127,12 +171,18 @@ PRIVATE void switch_address_space_idle(void)
*===========================================================================*/
PRIVATE void idle(void)
{
struct proc * p;
/* 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.
*/
p = get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc);
if (priv(p)->s_flags & BILLABLE)
get_cpulocal_var(bill_ptr) = p;
switch_address_space_idle();
/* start accounting for the idle time */
@ -184,9 +234,6 @@ not_runnable_pick_new:
* process. If there is still nothing runnable we "schedule" IDLE again
*/
while (!(p = pick_proc())) {
p = get_cpulocal_var(proc_ptr) = proc_addr(IDLE);
if (priv(p)->s_flags & BILLABLE)
get_cpulocal_var(bill_ptr) = p;
idle();
}

View file

@ -17,6 +17,19 @@
#if USE_GETINFO
#include <minix/u64.h>
PRIVATE void update_idle_time(void)
{
int i;
struct proc * idl = proc_addr(IDLE);
for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
idl->p_cycles = add64(idl->p_cycles,
get_cpu_var(i, idle_proc).p_cycles);
}
}
/*===========================================================================*
* do_getinfo *
*===========================================================================*/
@ -64,6 +77,7 @@ PUBLIC int do_getinfo(struct proc * caller, message * m_ptr)
break;
}
case GET_PROCTAB: {
update_idle_time();
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
src_vir = (vir_bytes) proc;
break;