]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - CPU local idle stub
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:21 +0000 (14:10 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:21 +0000 (14:10 +0000)
- each CPU has its own pseudo idle process and its structure

- idle cycles accounting is agregated when exporting to userspace

kernel/arch/i386/arch_smp.c
kernel/cpulocals.h
kernel/proc.c
kernel/system/do_getinfo.c

index f381b7b9a4ef8cc073ce8c9245db6a9a5d912d25..7c72ca1248f3d61af2b8cac71b107d2e7d29f5ab 100644 (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);
index 9c9be2db052debd30644531fcbc465cff61e1ed6..f9faefa9a25056806168140848ccba890e7502ac 100644 (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
index 90d5d87ba1e80c9202557f6c7396b23c3518a347..3ded1a3313ea82a0ad4bcf8821a29b46b561323e 100644 (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();
        }
 
index 342ebf83e15d5b177e47fee5313d95b9dbc0daf3..5bcfc9b31c4f56586886889a1263cc6cc53ae3e0 100644 (file)
 
 #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;