Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Track which process a CPU is running/has last run on by ...



details:   https://anonhg.NetBSD.org/src/rev/c1f690200ba3
branches:  trunk
changeset: 486939:c1f690200ba3
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed May 31 05:02:31 2000 +0000

description:
Track which process a CPU is running/has last run on by adding a
p_cpu member to struct proc.  Use this in certain places when
accessing scheduler state, etc.  For the single-processor case,
just initialize p_cpu in fork1() to avoid having to set it in the
low-level context switch code on platforms which will never have
multiprocessing.

While I'm here, comment a few places where there are known issues
for the SMP implementation.

diffstat:

 sys/kern/init_main.c     |  10 +++++---
 sys/kern/kern_fork.c     |  14 +++++++++++-
 sys/kern/kern_ktrace.c   |   6 +++-
 sys/kern/kern_resource.c |  11 ++++-----
 sys/kern/kern_subr.c     |   6 +++-
 sys/kern/kern_synch.c    |  53 +++++++++++++++++++++++++++++++++++++++++------
 sys/kern/kern_sysctl.c   |  13 +++++------
 sys/kern/kern_time.c     |  14 +++++++++--
 sys/sys/proc.h           |   4 ++-
 9 files changed, 98 insertions(+), 33 deletions(-)

diffs (truncated from 317 to 300 lines):

diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/init_main.c
--- a/sys/kern/init_main.c      Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/init_main.c      Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: init_main.c,v 1.170 2000/05/28 18:52:32 jhawk Exp $    */
+/*     $NetBSD: init_main.c,v 1.171 2000/05/31 05:02:31 thorpej Exp $  */
 
 /*
  * Copyright (c) 1995 Christopher G. Demetriou.  All rights reserved.
@@ -197,6 +197,7 @@
         */
        p = &proc0;
        curproc = p;
+       p->p_cpu = curcpu();
        /*
         * Attempt to find console and initialize
         * in case of early panic or other messages.
@@ -463,11 +464,12 @@
         * munched in mi_switch() after the time got set.
         */
        proclist_lock_read();
-       s = splclock();         /* so we can read time */
+       s = splhigh();          /* block clock and statclock */
        for (p = LIST_FIRST(&allproc); p != NULL;
             p = LIST_NEXT(p, p_list)) {
-               p->p_stats->p_start = curcpu()->ci_schedstate.spc_runtime =
-                   mono_time = boottime = time;
+               p->p_stats->p_start = mono_time = boottime = time;
+               if (p->p_cpu != NULL)
+                       p->p_cpu->ci_schedstate.spc_runtime = time;
                p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
        }
        splx(s);
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c      Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_fork.c      Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_fork.c,v 1.65 2000/05/28 05:49:05 thorpej Exp $   */
+/*     $NetBSD: kern_fork.c,v 1.66 2000/05/31 05:02:32 thorpej Exp $   */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -41,6 +41,7 @@
  */
 
 #include "opt_ktrace.h"
+#include "opt_multiprocessor.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -273,6 +274,17 @@
        memcpy(&p2->p_startcopy, &p1->p_startcopy,
            (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
 
+#if !defined(MULTIPROCESSOR)
+       /*
+        * In the single-processor case, all processes will always run
+        * on the same CPU.  So, initialize the child's CPU to the parent's
+        * now.  In the multiprocessor case, the child's CPU will be
+        * initialized in the low-level context switch code when the
+        * process runs.
+        */
+       p2->p_cpu = p1->p_cpu;
+#endif /* ! MULTIPROCESSOR */
+
        /*
         * Duplicate sub-structures as needed.
         * Increase reference counts on shared objects.
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c    Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_ktrace.c    Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_ktrace.c,v 1.45 2000/05/29 22:29:01 sommerfeld Exp $      */
+/*     $NetBSD: kern_ktrace.c,v 1.46 2000/05/31 05:02:32 thorpej Exp $ */
 
 /*
  * Copyright (c) 1989, 1993
@@ -232,7 +232,9 @@
        buflen -= sizeof(struct ktr_genio);
 
        while (resid > 0) {
-               if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
+               KDASSERT(p->p_cpu != NULL);
+               KDASSERT(p->p_cpu == curcpu());
+               if (p->p_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
                        preempt(NULL);
 
                cnt = min(iov->iov_len, buflen);
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c  Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_resource.c  Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_resource.c,v 1.56 2000/05/26 21:20:30 thorpej Exp $       */
+/*     $NetBSD: kern_resource.c,v 1.57 2000/05/31 05:02:32 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -382,11 +382,10 @@
        sec = p->p_rtime.tv_sec;
        usec = p->p_rtime.tv_usec;
        if (p->p_stat == SONPROC) {
-               /*
-                * XXX curcpu() is wrong -- needs to be the CPU the
-                * XXX process is running on. --thorpej
-                */
-               struct schedstate_percpu *spc = &curcpu()->ci_schedstate;
+               struct schedstate_percpu *spc;
+
+               KDASSERT(p->p_cpu != NULL);
+               spc = &p->p_cpu->ci_schedstate;
 
                /*
                 * Adjust for the current time slice.  This is actually fairly
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_subr.c
--- a/sys/kern/kern_subr.c      Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_subr.c      Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_subr.c,v 1.68 2000/05/27 01:43:27 enami Exp $     */
+/*     $NetBSD: kern_subr.c,v 1.69 2000/05/31 05:02:33 thorpej Exp $   */
 
 /*-
  * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
@@ -145,7 +145,9 @@
                switch (uio->uio_segflg) {
 
                case UIO_USERSPACE:
-                       if (curcpu()->ci_schedstate.spc_flags &
+                       KDASSERT(p->p_cpu != NULL);
+                       KDASSERT(p->p_cpu == curcpu());
+                       if (p->p_cpu->ci_schedstate.spc_flags &
                            SPCF_SHOULDYIELD)
                                preempt(NULL);
                        if (uio->uio_rw == UIO_READ)
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_synch.c
--- a/sys/kern/kern_synch.c     Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_synch.c     Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_synch.c,v 1.75 2000/05/27 05:00:48 thorpej Exp $  */
+/*     $NetBSD: kern_synch.c,v 1.76 2000/05/31 05:02:33 thorpej Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -424,7 +424,9 @@
        asm(".globl bpendtsleep ; bpendtsleep:");
 #endif
 resume:
-       curcpu()->ci_schedstate.spc_curpriority = p->p_usrpri;
+       KDASSERT(p->p_cpu != NULL);
+       KDASSERT(p->p_cpu == curcpu());
+       p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri;
        splx(s);
        p->p_flag &= ~P_SINTR;
        if (p->p_flag & P_TIMEOUT) {
@@ -679,11 +681,16 @@
 mi_switch(p)
        struct proc *p;
 {
-       struct schedstate_percpu *spc = &curcpu()->ci_schedstate;
+       struct schedstate_percpu *spc;
        struct rlimit *rlim;
        long s, u;
        struct timeval tv;
 
+       KDASSERT(p->p_cpu != NULL);
+       KDASSERT(p->p_cpu == curcpu());
+
+       spc = &p->p_cpu->ci_schedstate;
+
 #ifdef DEBUG
        if (p->p_simple_locks) {
                printf("p->p_simple_locks %d\n", p->p_simple_locks);
@@ -737,11 +744,20 @@
        spc->spc_flags &= ~SPCF_SWITCHCLEAR;
 
        /*
-        * Pick a new current process and record its start time.
+        * Pick a new current process and switch to it.  When we
+        * run again, we'll return back here.
         */
        uvmexp.swtch++;
        cpu_switch(p);
-       microtime(&spc->spc_runtime);
+
+       /*
+        * We're running again; record our new start time.  We might
+        * be running on a new CPU now, so don't use the cache'd
+        * schedstate_percpu pointer.
+        */
+       KDASSERT(p->p_cpu != NULL);
+       KDASSERT(p->p_cpu == curcpu());
+       microtime(&p->p_cpu->ci_schedstate.spc_runtime);
 }
 
 /*
@@ -803,8 +819,26 @@
        p->p_slptime = 0;
        if ((p->p_flag & P_INMEM) == 0)
                wakeup((caddr_t)&proc0);
-       else if (p->p_priority < curcpu()->ci_schedstate.spc_curpriority)
+       else if (p->p_priority < curcpu()->ci_schedstate.spc_curpriority) {
+               /*
+                * XXXSMP
+                * This is wrong.  It will work, but what really
+                * needs to happen is:
+                *
+                *      - Need to check if p is higher priority
+                *        than the process currently running on
+                *        the CPU p last ran on (let p_cpu persist
+                *        after a context switch?), and preempt
+                *        that one (or, if there is no process
+                *        there, simply need_resched() that CPU.
+                *
+                *      - Failing that, traverse a list of
+                *        available CPUs and need_resched() the
+                *        CPU with the lowest priority that's
+                *        lower than p's.
+                */
                need_resched();
+       }
 }
 
 /*
@@ -821,8 +855,13 @@
        newpriority = PUSER + p->p_estcpu + NICE_WEIGHT * (p->p_nice - NZERO);
        newpriority = min(newpriority, MAXPRI);
        p->p_usrpri = newpriority;
-       if (newpriority < curcpu()->ci_schedstate.spc_curpriority)
+       if (newpriority < curcpu()->ci_schedstate.spc_curpriority) {
+               /*
+                * XXXSMP
+                * Same applies as in setrunnable() above.
+                */
                need_resched();
+       }
 }
 
 /*
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c    Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_sysctl.c    Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sysctl.c,v 1.65 2000/05/27 04:52:36 thorpej Exp $ */
+/*     $NetBSD: kern_sysctl.c,v 1.66 2000/05/31 05:02:34 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -1226,12 +1226,11 @@
        ki->p_pctcpu = p->p_pctcpu;
        ki->p_swtime = p->p_swtime;
        ki->p_slptime = p->p_slptime;
-       /*
-        * XXX curcpu() is wrong; should be CPU process is running on.
-        * XXX   --thorpej
-        */
-       ki->p_schedflags = (p->p_stat == SONPROC) ?
-           curcpu()->ci_schedstate.spc_flags : 0;
+       if (p->p_stat == SONPROC) {
+               KDASSERT(p->p_cpu != NULL);
+               ki->p_schedflags = p->p_cpu->ci_schedstate.spc_flags;
+       } else
+               ki->p_schedflags = 0;
 
        ki->p_uticks = p->p_uticks;
        ki->p_sticks = p->p_sticks;
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/kern/kern_time.c
--- a/sys/kern/kern_time.c      Wed May 31 04:57:20 2000 +0000
+++ b/sys/kern/kern_time.c      Wed May 31 05:02:31 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_time.c,v 1.46 2000/05/26 21:20:32 thorpej Exp $   */
+/*     $NetBSD: kern_time.c,v 1.47 2000/05/31 05:02:34 thorpej Exp $   */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -113,7 +113,7 @@
        struct timeval *tv;
 {
        struct timeval delta;
-       struct schedstate_percpu *spc = &curcpu()->ci_schedstate;
+       struct cpu_info *ci;
        int s;
 
        /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
@@ -128,7 +128,15 @@
        time = *tv;
        (void) spllowersoftclock();
        timeradd(&boottime, &delta, &boottime);
-       timeradd(&spc->spc_runtime, &delta, &spc->spc_runtime);
+       /*
+        * XXXSMP
+        * This is wrong.  We should traverse a list of all
+        * CPUs and add the delta to the runtime of those
+        * CPUs which have a process on them.
+        */
+       ci = curcpu();
+       timeradd(&ci->ci_schedstate.spc_runtime, &delta,
+           &ci->ci_schedstate.spc_runtime);
 #      if defined(NFS) || defined(NFSSERVER)
                nqnfs_lease_updatetime(delta.tv_sec);
 #      endif
diff -r 162a91fc7fb4 -r c1f690200ba3 sys/sys/proc.h



Home | Main Index | Thread Index | Old Index