summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2000-03-03 16:58:50 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2000-03-03 16:58:50 +0000
commit2784d9216b447abfa133e8598a58d0b918aae037 (patch)
treecd9400448982b19ddadcb3f59926b8cec78ba3ac /sys/kern
parent14edc67da50a85d8cd0bdaf6ecbdc84586572985 (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/kern')
-rw-r--r--sys/kern/kern_subr.c31
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.
*/