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.
This commit is contained in:
thorpej 2000-05-31 05:02:31 +00:00
parent 65ace9d5d8
commit 956b3ca3b3
9 changed files with 98 additions and 33 deletions

View File

@ -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 @@ main()
*/
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 @@ main()
* 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);

View File

@ -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 @@ again:
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.

View File

@ -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 @@ ktrgenio(p, fd, rw, iov, len, error)
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);

View File

@ -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 @@ calcru(p, up, sp, ip)
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

View File

@ -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 @@ uiomove(buf, n, uio)
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)

View File

@ -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 @@ tsleep(ident, priority, wmesg, timo)
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 @@ void
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 @@ mi_switch(p)
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 @@ setrunnable(p)
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 @@ resetpriority(p)
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();
}
}
/*

View File

@ -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 @@ fill_kproc2(p, ki)
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;

View File

@ -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 @@ settime(tv)
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 @@ settime(tv)
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

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.96 2000/05/28 05:49:06 thorpej Exp $ */
/* $NetBSD: proc.h,v 1.97 2000/05/31 05:02:36 thorpej Exp $ */
/*-
* Copyright (c) 1986, 1989, 1991, 1993
@ -135,6 +135,8 @@ struct proc {
int p_exitsig; /* signal to sent to parent on exit */
int p_flag; /* P_* flags. */
struct cpu_info * __volatile p_cpu; /* CPU we're running on if
SONPROC */
u_char p_unused; /* XXX: used to be emulation flag */
char p_stat; /* S* process status. */
char p_pad1[2];