Adjust pamp_growkernel(), elf_brand_inuse(), and ktrace() to use
authorMatthew Dillon <dillon@dragonflybsd.org>
Thu, 25 May 2006 04:17:09 +0000 (04:17 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Thu, 25 May 2006 04:17:09 +0000 (04:17 +0000)
allproc_scan() instead of scanning the process list manually.

sys/i386/i386/db_trace.c
sys/i386/i386/pmap.c
sys/kern/imgact_elf.c
sys/kern/kern_ktrace.c
sys/platform/pc32/i386/db_trace.c
sys/platform/pc32/i386/pmap.c

index 651d455..d010191 100644 (file)
@@ -24,7 +24,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/i386/i386/db_trace.c,v 1.35.2.3 2002/02/21 22:31:25 silby Exp $
- * $DragonFly: src/sys/i386/i386/Attic/db_trace.c,v 1.11 2005/11/14 18:50:03 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/db_trace.c,v 1.12 2006/05/25 04:17:07 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -294,12 +294,10 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                        callpc = PC_REGS(&ddb_regs);
                } else {
 
-                       /* sx_slock(&allproc_lock); */
                        FOREACH_PROC_IN_SYSTEM(p) {
                                if (p->p_pid == pid)
                                        break;
                        }
-                       /* sx_sunlock(&allproc_lock); */
                        if (p == NULL) {
                                db_printf("pid %d not found\n", pid);
                                return;
index 5ad975c..24044c5 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
  * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.54 2005/11/22 08:41:00 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.55 2006/05/25 04:17:07 dillon Exp $
  */
 
 /*
@@ -1338,13 +1338,18 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
     0, 0, kvm_free, "IU", "Amount of KVM free");
 
 /*
- * grow the number of kernel page table entries, if needed
+ * Grow the number of kernel page table entries, if needed.
  */
+struct pmap_growkernel_info {
+       pd_entry_t newpdir;
+};
+
+static int pmap_growkernel_callback(struct proc *p, void *data);
+
 void
 pmap_growkernel(vm_offset_t addr)
 {
-       struct proc *p;
-       struct pmap *pmap;
+       struct pmap_growkernel_info info;
        vm_offset_t ptppaddr;
        vm_page_t nkpg;
        pd_entry_t newpdir;
@@ -1373,26 +1378,41 @@ pmap_growkernel(vm_offset_t addr)
                if (nkpg == NULL)
                        panic("pmap_growkernel: no memory to grow kernel");
 
-               nkpt++;
-
                vm_page_wire(nkpg);
                ptppaddr = VM_PAGE_TO_PHYS(nkpg);
                pmap_zero_page(ptppaddr);
                newpdir = (pd_entry_t) (ptppaddr | PG_V | PG_RW | PG_A | PG_M);
                pdir_pde(PTD, kernel_vm_end) = newpdir;
-
-               FOREACH_PROC_IN_SYSTEM(p) {
-                       if (p->p_vmspace) {
-                               pmap = vmspace_pmap(p->p_vmspace);
-                               *pmap_pde(pmap, kernel_vm_end) = newpdir;
-                       }
-               }
                *pmap_pde(kernel_pmap, kernel_vm_end) = newpdir;
+               nkpt++;
+
+               /*
+                * vm_fork and friends copy nkpt page table pages to the high
+                * side of a new process's pmap.  This occurs after the 
+                * process has been added to allproc, so scanning the proc
+                * list afterwords should be sufficient to fixup existing
+                * processes.
+                */
+               info.newpdir = newpdir;
+               allproc_scan(pmap_growkernel_callback, &info);
                kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1);
        }
        crit_exit();
 }
 
+static int
+pmap_growkernel_callback(struct proc *p, void *data)
+{
+       struct pmap_growkernel_info *info = data;
+       struct pmap *pmap;
+
+       if (p->p_vmspace) {
+               pmap = vmspace_pmap(p->p_vmspace);
+               *pmap_pde(pmap, kernel_vm_end) = info->newpdir;
+       }
+       return(0);
+}
+
 /*
  *     Retire the given physical map from service.
  *     Should only be called if the map contains
@@ -3271,64 +3291,6 @@ pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size)
 }
 
 
-#if defined(PMAP_DEBUG)
-int
-pmap_pid_dump(int pid)
-{
-       pmap_t pmap;
-       struct proc *p;
-       int npte = 0;
-       int index;
-       FOREACH_PROC_IN_SYSTEM(p) {
-               if (p->p_pid != pid)
-                       continue;
-
-               if (p->p_vmspace) {
-                       int i,j;
-                       index = 0;
-                       pmap = vmspace_pmap(p->p_vmspace);
-                       for(i=0;i<1024;i++) {
-                               pd_entry_t *pde;
-                               unsigned *pte;
-                               unsigned base = i << PDRSHIFT;
-                               
-                               pde = &pmap->pm_pdir[i];
-                               if (pde && pmap_pde_v(pde)) {
-                                       for(j=0;j<1024;j++) {
-                                               unsigned va = base + (j << PAGE_SHIFT);
-                                               if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) {
-                                                       if (index) {
-                                                               index = 0;
-                                                               printf("\n");
-                                                       }
-                                                       return npte;
-                                               }
-                                               pte = pmap_pte_quick( pmap, va);
-                                               if (pte && pmap_pte_v(pte)) {
-                                                       vm_offset_t pa;
-                                                       vm_page_t m;
-                                                       pa = *(int *)pte;
-                                                       m = PHYS_TO_VM_PAGE(pa);
-                                                       printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x",
-                                                               va, pa, m->hold_count, m->wire_count, m->flags);
-                                                       npte++;
-                                                       index++;
-                                                       if (index >= 2) {
-                                                               index = 0;
-                                                               printf("\n");
-                                                       } else {
-                                                               printf(" ");
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       return npte;
-}
-#endif
-
 #if defined(DEBUG)
 
 static void    pads (pmap_t pm);
index d52ba46..c74fda4 100644 (file)
@@ -27,7 +27,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $
- * $DragonFly: src/sys/kern/imgact_elf.c,v 1.38 2006/05/19 07:33:45 dillon Exp $
+ * $DragonFly: src/sys/kern/imgact_elf.c,v 1.39 2006/05/25 04:17:09 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -193,20 +193,41 @@ elf_remove_brand_entry(Elf_Brandinfo *entry)
        return 0;
 }
 
+/*
+ * Check if an elf brand is being used anywhere in the system.
+ *
+ * Used by the linux emulatino module unloader.  This isn't safe from
+ * races.
+ */
+struct elf_brand_inuse_info {
+       int rval;
+       Elf_Brandinfo *entry;
+};
+
+static int elf_brand_inuse_callback(struct proc *p, void *data);
+
 int
 elf_brand_inuse(Elf_Brandinfo *entry)
 {
-       struct proc *p;
-       int rval = FALSE;
+       struct elf_brand_inuse_info info;
 
-       FOREACH_PROC_IN_SYSTEM(p) {
-               if (p->p_sysent == entry->sysvec) {
-                       rval = TRUE;
-                       break;
-               }
-       }
+       info.rval = FALSE;
+       info.entry = entry;
+       allproc_scan(elf_brand_inuse_callback, entry);
+       return (info.rval);
+}
 
-       return (rval);
+static
+int
+elf_brand_inuse_callback(struct proc *p, void *data)
+{
+       struct elf_brand_inuse_info *info = data;
+
+       if (p->p_sysent == info->entry->sysvec) {
+               info->rval = TRUE;
+               return(-1);
+       }
+       return(0);
 }
 
 static int
index 3445c29..8e39da7 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)kern_ktrace.c       8.2 (Berkeley) 9/23/93
  * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.6 2002/07/05 22:36:38 darrenr Exp $
- * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.25 2006/05/17 20:35:33 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.26 2006/05/25 04:17:09 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -206,14 +206,25 @@ ktrcsw(struct proc *p, int out, int user)
 
 /* Interface and common routines */
 
+#ifdef KTRACE
 /*
  * ktrace system call
  */
-/* ARGSUSED */
+struct ktrace_clear_info {
+       ktrace_node_t tracenode;
+       int rootclear;
+       int error;
+};
+
+static int ktrace_clear_callback(struct proc *p, void *data);
+
+#endif
+
 int
 ktrace(struct ktrace_args *uap)
 {
 #ifdef KTRACE
+       struct ktrace_clear_info info;
        struct thread *td = curthread;
        struct proc *curp = td->td_proc;
        struct proc *p;
@@ -255,18 +266,11 @@ ktrace(struct ktrace_args *uap)
         * in the world.
         */
        if (ops == KTROP_CLEARFILE) {
-again:
-               FOREACH_PROC_IN_SYSTEM(p) {
-                       if (p->p_tracenode->kn_vp == tracenode->kn_vp) {
-                               if (ktrcanset(curp, p)) {
-                                       ktrdestroy(&p->p_tracenode);
-                                       p->p_traceflag = 0;
-                                       goto again;
-                               } else {
-                                       error = EPERM;
-                               }
-                       }
-               }
+               info.tracenode = tracenode;
+               info.error = 0;
+               info.rootclear = 0;
+               allproc_scan(ktrace_clear_callback, &info);
+               error = info.error;
                goto done;
        }
        /*
@@ -320,6 +324,36 @@ done:
 #endif
 }
 
+#ifdef KTRACE
+
+/*
+ * NOTE: NOT MPSAFE (yet)
+ */
+static int
+ktrace_clear_callback(struct proc *p, void *data)
+{
+       struct ktrace_clear_info *info = data;
+
+       if (info->rootclear) {
+               if (p->p_tracenode == info->tracenode) {
+                       ktrdestroy(&p->p_tracenode);
+                       p->p_traceflag = 0;
+               }
+       } else {
+               if (p->p_tracenode->kn_vp == info->tracenode->kn_vp) {
+                       if (ktrcanset(curproc, p)) {
+                               ktrdestroy(&p->p_tracenode);
+                               p->p_traceflag = 0;
+                       } else {
+                               info->error = EPERM;
+                       }
+               }
+       }
+       return(0);
+}
+
+#endif
+
 /*
  * utrace system call
  */
@@ -373,6 +407,11 @@ ktrdestroy(struct ktrace_node **tracenodep)
        }
 }
 
+/*
+ * This allows a process to inherit a ref on a tracenode and is also used
+ * as a temporary ref to prevent a tracenode from being destroyed out from
+ * under an active operation.
+ */
 ktrace_node_t
 ktrinherit(ktrace_node_t tracenode)
 {
@@ -445,6 +484,7 @@ ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs,
 static void
 ktrwrite(struct proc *p, struct ktr_header *kth, struct uio *uio)
 {
+       struct ktrace_clear_info info;
        struct uio auio;
        struct iovec aiov[2];
        int error;
@@ -493,14 +533,10 @@ ktrwrite(struct proc *p, struct ktr_header *kth, struct uio *uio)
                 */
                log(LOG_NOTICE,
                    "ktrace write failed, errno %d, tracing stopped\n", error);
-retry:
-               FOREACH_PROC_IN_SYSTEM(p) {
-                       if (p->p_tracenode == tracenode) {
-                               ktrdestroy(&p->p_tracenode);
-                               p->p_traceflag = 0;
-                               goto retry;
-                       }
-               }
+               info.tracenode = tracenode;
+               info.error = 0;
+               info.rootclear = 1;
+               allproc_scan(ktrace_clear_callback, &info);
        }
        ktrdestroy(&tracenode);
 }
index b7dc338..e8f7860 100644 (file)
@@ -24,7 +24,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/i386/i386/db_trace.c,v 1.35.2.3 2002/02/21 22:31:25 silby Exp $
- * $DragonFly: src/sys/platform/pc32/i386/db_trace.c,v 1.11 2005/11/14 18:50:03 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/db_trace.c,v 1.12 2006/05/25 04:17:07 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -294,12 +294,10 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                        callpc = PC_REGS(&ddb_regs);
                } else {
 
-                       /* sx_slock(&allproc_lock); */
                        FOREACH_PROC_IN_SYSTEM(p) {
                                if (p->p_pid == pid)
                                        break;
                        }
-                       /* sx_sunlock(&allproc_lock); */
                        if (p == NULL) {
                                db_printf("pid %d not found\n", pid);
                                return;
index 12e9602..5b76a56 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
  * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.54 2005/11/22 08:41:00 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.55 2006/05/25 04:17:07 dillon Exp $
  */
 
 /*
@@ -1338,13 +1338,18 @@ SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
     0, 0, kvm_free, "IU", "Amount of KVM free");
 
 /*
- * grow the number of kernel page table entries, if needed
+ * Grow the number of kernel page table entries, if needed.
  */
+struct pmap_growkernel_info {
+       pd_entry_t newpdir;
+};
+
+static int pmap_growkernel_callback(struct proc *p, void *data);
+
 void
 pmap_growkernel(vm_offset_t addr)
 {
-       struct proc *p;
-       struct pmap *pmap;
+       struct pmap_growkernel_info info;
        vm_offset_t ptppaddr;
        vm_page_t nkpg;
        pd_entry_t newpdir;
@@ -1373,26 +1378,41 @@ pmap_growkernel(vm_offset_t addr)
                if (nkpg == NULL)
                        panic("pmap_growkernel: no memory to grow kernel");
 
-               nkpt++;
-
                vm_page_wire(nkpg);
                ptppaddr = VM_PAGE_TO_PHYS(nkpg);
                pmap_zero_page(ptppaddr);
                newpdir = (pd_entry_t) (ptppaddr | PG_V | PG_RW | PG_A | PG_M);
                pdir_pde(PTD, kernel_vm_end) = newpdir;
-
-               FOREACH_PROC_IN_SYSTEM(p) {
-                       if (p->p_vmspace) {
-                               pmap = vmspace_pmap(p->p_vmspace);
-                               *pmap_pde(pmap, kernel_vm_end) = newpdir;
-                       }
-               }
                *pmap_pde(kernel_pmap, kernel_vm_end) = newpdir;
+               nkpt++;
+
+               /*
+                * vm_fork and friends copy nkpt page table pages to the high
+                * side of a new process's pmap.  This occurs after the 
+                * process has been added to allproc, so scanning the proc
+                * list afterwords should be sufficient to fixup existing
+                * processes.
+                */
+               info.newpdir = newpdir;
+               allproc_scan(pmap_growkernel_callback, &info);
                kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1);
        }
        crit_exit();
 }
 
+static int
+pmap_growkernel_callback(struct proc *p, void *data)
+{
+       struct pmap_growkernel_info *info = data;
+       struct pmap *pmap;
+
+       if (p->p_vmspace) {
+               pmap = vmspace_pmap(p->p_vmspace);
+               *pmap_pde(pmap, kernel_vm_end) = info->newpdir;
+       }
+       return(0);
+}
+
 /*
  *     Retire the given physical map from service.
  *     Should only be called if the map contains
@@ -3271,64 +3291,6 @@ pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size)
 }
 
 
-#if defined(PMAP_DEBUG)
-int
-pmap_pid_dump(int pid)
-{
-       pmap_t pmap;
-       struct proc *p;
-       int npte = 0;
-       int index;
-       FOREACH_PROC_IN_SYSTEM(p) {
-               if (p->p_pid != pid)
-                       continue;
-
-               if (p->p_vmspace) {
-                       int i,j;
-                       index = 0;
-                       pmap = vmspace_pmap(p->p_vmspace);
-                       for(i=0;i<1024;i++) {
-                               pd_entry_t *pde;
-                               unsigned *pte;
-                               unsigned base = i << PDRSHIFT;
-                               
-                               pde = &pmap->pm_pdir[i];
-                               if (pde && pmap_pde_v(pde)) {
-                                       for(j=0;j<1024;j++) {
-                                               unsigned va = base + (j << PAGE_SHIFT);
-                                               if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) {
-                                                       if (index) {
-                                                               index = 0;
-                                                               printf("\n");
-                                                       }
-                                                       return npte;
-                                               }
-                                               pte = pmap_pte_quick( pmap, va);
-                                               if (pte && pmap_pte_v(pte)) {
-                                                       vm_offset_t pa;
-                                                       vm_page_t m;
-                                                       pa = *(int *)pte;
-                                                       m = PHYS_TO_VM_PAGE(pa);
-                                                       printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x",
-                                                               va, pa, m->hold_count, m->wire_count, m->flags);
-                                                       npte++;
-                                                       index++;
-                                                       if (index >= 2) {
-                                                               index = 0;
-                                                               printf("\n");
-                                                       } else {
-                                                               printf(" ");
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       return npte;
-}
-#endif
-
 #if defined(DEBUG)
 
 static void    pads (pmap_t pm);