If we attempted reschedule two times without suceeding, uiomove will yield,
authorart <art@openbsd.org>
Fri, 3 Mar 2000 16:58:49 +0000 (16:58 +0000)
committerart <art@openbsd.org>
Fri, 3 Mar 2000 16:58:49 +0000 (16:58 +0000)
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.

sys/kern/kern_subr.c

index 4a6321e..7c7550b 100644 (file)
@@ -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 $     */
 
 /*
 #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.
  */