Source-Changes-HG archive

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

[src/trunk]: src change uvm_uarea_alloc() to indicate whether the returned ua...



details:   https://anonhg.NetBSD.org/src/rev/69a9d6e80eb2
branches:  trunk
changeset: 539457:69a9d6e80eb2
user:      chs <chs%NetBSD.org@localhost>
date:      Sun Nov 17 08:32:43 2002 +0000

description:
change uvm_uarea_alloc() to indicate whether the returned uarea is already
backed by physical pages (ie. because it reused a previously-freed one),
so that we can skip a bunch of useless work in that case.
this fixes the underlying problem behind PR 18543, and also speeds up fork()
quite a bit (eg. 7% on my pc, 1% on my ultra2) when we get a cache hit.

diffstat:

 share/man/man9/uvm.9     |  17 +++++++++++------
 sys/arch/arm/arm32/cpu.c |  15 ++++++++-------
 sys/kern/kern_fork.c     |  11 ++++++-----
 sys/kern/kern_kthread.c  |   6 +++---
 sys/uvm/uvm_extern.h     |   4 ++--
 sys/uvm/uvm_glue.c       |  33 ++++++++++++++++++++-------------
 6 files changed, 50 insertions(+), 36 deletions(-)

diffs (240 lines):

diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 share/man/man9/uvm.9
--- a/share/man/man9/uvm.9      Sun Nov 17 07:21:11 2002 +0000
+++ b/share/man/man9/uvm.9      Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: uvm.9,v 1.36 2002/09/27 07:52:48 wiz Exp $
+.\"    $NetBSD: uvm.9,v 1.37 2002/11/17 08:32:44 chs Exp $
 .\"
 .\" Copyright (c) 1998 Matthew R. Green
 .\" All rights reserved.
@@ -133,10 +133,10 @@
 .Fn uvmspace_share "struct proc *p1" "struct proc *p2"
 .Ft void
 .Fn uvmspace_unshare "struct proc *p"
-.Ft vaddr_t
-.Fn uvm_uarea_alloc "void"
+.Ft boolean_t
+.Fn uvm_uarea_alloc "vaddr_t *uaddrp"
 .Ft void
-.Fn uvm_uarea_free "vaddr_t va"
+.Fn uvm_uarea_free "vaddr_t uaddr"
 .nr nS 0
 .Pp
 .Fn uvm_map
@@ -359,8 +359,13 @@
 .Fn uvmspace_fork .
 .Pp
 .Fn uvm_uarea_alloc
-allocates virtual space for a u-area (i.e., a kernel stack) and returns
-its virtual address.
+allocates virtual space for a u-area (i.e., a kernel stack) and stores
+its virtual address in
+.Fa *uaddrp .
+The return value is
+.Dv TRUE
+if the u-area is already backed by wired physical memory, otherwise
+.Dv FALSE .
 .Pp
 .Fn uvm_uarea_free
 frees a u-area allocated with
diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 sys/arch/arm/arm32/cpu.c
--- a/sys/arch/arm/arm32/cpu.c  Sun Nov 17 07:21:11 2002 +0000
+++ b/sys/arch/arm/arm32/cpu.c  Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpu.c,v 1.45 2002/10/13 21:14:28 chris Exp $   */
+/*     $NetBSD: cpu.c,v 1.46 2002/11/17 08:32:43 chs Exp $     */
 
 /*
  * Copyright (c) 1995 Mark Brinicombe.
@@ -45,7 +45,7 @@
 
 #include <sys/param.h>
 
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.45 2002/10/13 21:14:28 chris Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.46 2002/11/17 08:32:43 chs Exp $");
 
 #include <sys/systm.h>
 #include <sys/malloc.h>
@@ -527,11 +527,12 @@
         * Generate a kernel stack and PCB (in essence, a u-area) for the
         * new CPU.
         */
-       uaddr = uvm_uarea_alloc();
-       error = uvm_fault_wire(kernel_map, uaddr, uaddr + USPACE,
-           VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE);
-       if (error)
-               return error;
+       if (uvm_uarea_alloc(&uaddr)) {
+               error = uvm_fault_wire(kernel_map, uaddr, uaddr + USPACE,
+                   VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE);
+               if (error)
+                       return error;
+       }
        ci->ci_idlepcb = pcb = (struct pcb *)uaddr;
 
        /*
diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c      Sun Nov 17 07:21:11 2002 +0000
+++ b/sys/kern/kern_fork.c      Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_fork.c,v 1.98 2002/11/13 00:51:02 provos Exp $    */
+/*     $NetBSD: kern_fork.c,v 1.99 2002/11/17 08:32:44 chs Exp $       */
 
 /*-
  * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.98 2002/11/13 00:51:02 provos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.99 2002/11/17 08:32:44 chs Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_systrace.h"
@@ -198,6 +198,7 @@
        uid_t           uid;
        int             count, s;
        vaddr_t         uaddr;
+       boolean_t       inmem;
        static int      nextpid, pidchecked;
 
        /*
@@ -231,10 +232,10 @@
         * Allocate virtual address space for the U-area now, while it
         * is still easy to abort the fork operation if we're out of
         * kernel virtual address space.  The actual U-area pages will
-        * be allocated and wired in uvm_fork().
+        * be allocated and wired in uvm_fork() if needed.
         */
 
-       uaddr = uvm_uarea_alloc();
+       inmem = uvm_uarea_alloc(&uaddr);
        if (__predict_false(uaddr == 0)) {
                (void)chgproccnt(uid, -1);
                nprocs--;
@@ -280,7 +281,7 @@
         * Increase reference counts on shared objects.
         * The p_stats and p_sigacts substructs are set in uvm_fork().
         */
-       p2->p_flag = P_INMEM | (p1->p_flag & P_SUGID);
+       p2->p_flag = (inmem ? P_INMEM : 0) | (p1->p_flag & P_SUGID);
        p2->p_emul = p1->p_emul;
        p2->p_execsw = p1->p_execsw;
 
diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 sys/kern/kern_kthread.c
--- a/sys/kern/kern_kthread.c   Sun Nov 17 07:21:11 2002 +0000
+++ b/sys/kern/kern_kthread.c   Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_kthread.c,v 1.13 2002/06/01 23:51:05 lukem Exp $  */
+/*     $NetBSD: kern_kthread.c,v 1.14 2002/11/17 08:32:44 chs Exp $    */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.13 2002/06/01 23:51:05 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.14 2002/11/17 08:32:44 chs Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -82,7 +82,7 @@
         * to init(8) when they exit.  init(8) can easily wait them
         * out for us.
         */
-       p2->p_flag |= P_INMEM | P_SYSTEM | P_NOCLDWAIT; /* XXX */
+       p2->p_flag |= P_SYSTEM | P_NOCLDWAIT;
 
        /* Name it as specified. */
        va_start(ap, fmt);
diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 sys/uvm/uvm_extern.h
--- a/sys/uvm/uvm_extern.h      Sun Nov 17 07:21:11 2002 +0000
+++ b/sys/uvm/uvm_extern.h      Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_extern.h,v 1.73 2002/09/22 07:20:31 chs Exp $      */
+/*     $NetBSD: uvm_extern.h,v 1.74 2002/11/17 08:32:45 chs Exp $      */
 
 /*
  *
@@ -572,7 +572,7 @@
 boolean_t              uvm_kernacc __P((caddr_t, size_t, int));
 __dead void            uvm_scheduler __P((void)) __attribute__((noreturn));
 void                   uvm_swapin __P((struct proc *));
-vaddr_t                        uvm_uarea_alloc(void);
+boolean_t              uvm_uarea_alloc(vaddr_t *);
 void                   uvm_uarea_free(vaddr_t);
 boolean_t              uvm_useracc __P((caddr_t, size_t, int));
 int                    uvm_vslock __P((struct proc *, caddr_t, size_t,
diff -r dfe5cda6a9d8 -r 69a9d6e80eb2 sys/uvm/uvm_glue.c
--- a/sys/uvm/uvm_glue.c        Sun Nov 17 07:21:11 2002 +0000
+++ b/sys/uvm/uvm_glue.c        Sun Nov 17 08:32:43 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_glue.c,v 1.60 2002/09/22 07:20:32 chs Exp $        */
+/*     $NetBSD: uvm_glue.c,v 1.61 2002/11/17 08:32:45 chs Exp $        */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_glue.c,v 1.60 2002/09/22 07:20:32 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_glue.c,v 1.61 2002/11/17 08:32:45 chs Exp $");
 
 #include "opt_kgdb.h"
 #include "opt_kstack.h"
@@ -290,15 +290,20 @@
         * Wire down the U-area for the process, which contains the PCB
         * and the kernel stack.  Wired state is stored in p->p_flag's
         * P_INMEM bit rather than in the vm_map_entry's wired count
-        * to prevent kernel_map fragmentation.
+        * to prevent kernel_map fragmentation.  If we reused a cached U-area,
+        * P_INMEM will already be set and we don't need to do anything.
         *
-        * Note the kernel stack gets read/write accesses right off
-        * the bat.
+        * Note the kernel stack gets read/write accesses right off the bat.
         */
-       error = uvm_fault_wire(kernel_map, (vaddr_t)up, (vaddr_t)up + USPACE,
-           VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE);
-       if (error)
-               panic("uvm_fork: uvm_fault_wire failed: %d", error);
+
+       if ((p2->p_flag & P_INMEM) == 0) {
+               error = uvm_fault_wire(kernel_map, (vaddr_t)up,
+                   (vaddr_t)up + USPACE, VM_FAULT_WIRE,
+                   VM_PROT_READ | VM_PROT_WRITE);
+               if (error)
+                       panic("uvm_fork: uvm_fault_wire failed: %d", error);
+               p2->p_flag |= P_INMEM;
+       }
 
 #ifdef KSTACK_CHECK_MAGIC
        /*
@@ -354,8 +359,8 @@
  * uvm_uarea_alloc: allocate a u-area
  */
 
-vaddr_t
-uvm_uarea_alloc(void)
+boolean_t
+uvm_uarea_alloc(vaddr_t *uaddrp)
 {
        vaddr_t uaddr;
 
@@ -367,10 +372,12 @@
        if (uaddr) {
                uvm_uareas = *(void **)uvm_uareas;
                uvm_nuarea--;
+               *uaddrp = uaddr;
+               return TRUE;
        } else {
-               uaddr = uvm_km_valloc_align(kernel_map, USPACE, USPACE_ALIGN);
+               *uaddrp = uvm_km_valloc_align(kernel_map, USPACE, USPACE_ALIGN);
+               return FALSE;
        }
-       return uaddr;
 }
 
 /*



Home | Main Index | Thread Index | Old Index