diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2000-03-03 16:58:50 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2000-03-03 16:58:50 +0000 |
commit | 2784d9216b447abfa133e8598a58d0b918aae037 (patch) | |
tree | cd9400448982b19ddadcb3f59926b8cec78ba3ac /sys | |
parent | 14edc67da50a85d8cd0bdaf6ecbdc84586572985 (diff) |
If we attempted reschedule two times without suceeding, uiomove will yield,
giving other processes a chance to run.
A process feeding a huge buffer to {read,write}{,v} on a file that doesn't
need to wait for I/O, could have hogged a lot of cpu in the kernel, blocking
all userland activity.
Based on a similiar fix in FreeBSD.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_subr.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 4a6321e1896..7c7550b9861 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_subr.c,v 1.10 1999/11/07 17:39:14 provos Exp $ */ +/* $OpenBSD: kern_subr.c,v 1.11 2000/03/03 16:58:49 art Exp $ */ /* $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $ */ /* @@ -46,6 +46,12 @@ #include <sys/proc.h> #include <sys/malloc.h> #include <sys/queue.h> +#include <sys/kernel.h> +#include <sys/resourcevar.h> + +void uio_yield __P((struct proc *)); + +#define UIO_NEED_YIELD (roundrobin_attempts >= 2) int uiomove(cp, n, uio) @@ -56,12 +62,15 @@ uiomove(cp, n, uio) register struct iovec *iov; u_int cnt; int error = 0; + struct proc *p; + + p = uio->uio_procp; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) panic("uiomove: mode"); - if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) - panic("uiomove proc"); + if (uio->uio_segflg == UIO_USERSPACE && p != curproc) + panic("uiomove: proc"); #endif while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; @@ -76,6 +85,8 @@ uiomove(cp, n, uio) switch (uio->uio_segflg) { case UIO_USERSPACE: + if (UIO_NEED_YIELD) + uio_yield(p); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else @@ -157,6 +168,20 @@ again: return (0); } +void +uio_yield(p) + struct proc *p; +{ + int s; + + p->p_priority = p->p_usrpri; + s = splstatclock(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + splx(s); +} + /* * General routine to allocate a hash table. */ |