diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 18 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/pmap.c | 10 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmap.c | 19 | ||||
-rw-r--r-- | sys/arch/i386/i386/pmapae.c | 20 | ||||
-rw-r--r-- | sys/kern/vfs_biomem.c | 4 | ||||
-rw-r--r-- | sys/uvm/uvm_aobj.c | 13 | ||||
-rw-r--r-- | sys/uvm/uvm_device.c | 6 | ||||
-rw-r--r-- | sys/uvm/uvm_init.c | 8 | ||||
-rw-r--r-- | sys/uvm/uvm_map.c | 9 | ||||
-rw-r--r-- | sys/uvm/uvm_object.h | 16 | ||||
-rw-r--r-- | sys/uvm/uvm_page.c | 176 | ||||
-rw-r--r-- | sys/uvm/uvm_page.h | 21 | ||||
-rw-r--r-- | sys/uvm/uvm_vnode.c | 30 |
13 files changed, 93 insertions, 257 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index b6ff88bef80..d7dfac863d5 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.49 2009/06/16 16:42:40 ariane Exp $ */ +/* $OpenBSD: pmap.c,v 1.50 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -567,7 +567,7 @@ pmap_bootstrap(paddr_t first_avail, paddr_t max_pa) kpm = pmap_kernel(); for (i = 0; i < PTP_LEVELS - 1; i++) { kpm->pm_obj[i].pgops = NULL; - TAILQ_INIT(&kpm->pm_obj[i].memq); + RB_INIT(&kpm->pm_obj[i].memt); kpm->pm_obj[i].uo_npages = 0; kpm->pm_obj[i].uo_refs = 1; kpm->pm_ptphint[i] = NULL; @@ -832,10 +832,10 @@ pmap_freepage(struct pmap *pmap, struct vm_page *ptp, int level, obj = &pmap->pm_obj[lidx]; pmap->pm_stats.resident_count--; if (pmap->pm_ptphint[lidx] == ptp) - pmap->pm_ptphint[lidx] = TAILQ_FIRST(&obj->memq); + pmap->pm_ptphint[lidx] = RB_ROOT(&obj->memt); ptp->wire_count = 0; uvm_pagerealloc(ptp, NULL, 0); - TAILQ_INSERT_TAIL(pagelist, ptp, listq); + TAILQ_INSERT_TAIL(pagelist, ptp, pageq); } void @@ -1019,7 +1019,7 @@ pmap_create(void) /* init uvm_object */ for (i = 0; i < PTP_LEVELS - 1; i++) { pmap->pm_obj[i].pgops = NULL; /* not a mappable object */ - TAILQ_INIT(&pmap->pm_obj[i].memq); + RB_INIT(&pmap->pm_obj[i].memt); pmap->pm_obj[i].uo_npages = 0; pmap->pm_obj[i].uo_refs = 1; pmap->pm_ptphint[i] = NULL; @@ -1091,7 +1091,7 @@ pmap_destroy(struct pmap *pmap) */ for (i = 0; i < PTP_LEVELS - 1; i++) { - while ((pg = TAILQ_FIRST(&pmap->pm_obj[i].memq)) != NULL) { + while ((pg = RB_ROOT(&pmap->pm_obj[i].memt)) != NULL) { KASSERT((pg->pg_flags & PG_BUSY) == 0); pg->wire_count = 0; @@ -1537,7 +1537,7 @@ pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags) PMAP_MAP_TO_HEAD_UNLOCK(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } @@ -1609,7 +1609,7 @@ pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags) PMAP_MAP_TO_HEAD_UNLOCK(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } @@ -1682,7 +1682,7 @@ pmap_page_remove(struct vm_page *pg) pmap_tlb_shootwait(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } diff --git a/sys/arch/hppa/hppa/pmap.c b/sys/arch/hppa/hppa/pmap.c index a2829a528c6..90c0d57273d 100644 --- a/sys/arch/hppa/hppa/pmap.c +++ b/sys/arch/hppa/hppa/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.141 2009/07/29 18:31:11 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.142 2009/08/06 15:28:14 oga Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -235,7 +235,7 @@ pmap_pde_release(struct pmap *pmap, vaddr_t va, struct vm_page *ptp) pmap_pde_set(pmap, va, 0); pmap->pm_stats.resident_count--; if (pmap->pm_ptphint == ptp) - pmap->pm_ptphint = TAILQ_FIRST(&pmap->pm_obj.memq); + pmap->pm_ptphint = RB_ROOT(&pmap->pm_obj.memt); ptp->wire_count = 0; #ifdef DIAGNOSTIC if (ptp->pg_flags & PG_BUSY) @@ -471,7 +471,7 @@ pmap_bootstrap(vstart) bzero(kpm, sizeof(*kpm)); simple_lock_init(&kpm->pm_lock); kpm->pm_obj.pgops = NULL; - TAILQ_INIT(&kpm->pm_obj.memq); + RB_INIT(&kpm->pm_obj.memt); kpm->pm_obj.uo_npages = 0; kpm->pm_obj.uo_refs = 1; kpm->pm_space = HPPA_SID_KERNEL; @@ -657,7 +657,7 @@ pmap_create() simple_lock_init(&pmap->pm_lock); pmap->pm_obj.pgops = NULL; /* currently not a mappable object */ - TAILQ_INIT(&pmap->pm_obj.memq); + RB_INIT(&pmap->pm_obj.memt); pmap->pm_obj.uo_npages = 0; pmap->pm_obj.uo_refs = 1; @@ -699,7 +699,7 @@ pmap_destroy(pmap) return; #ifdef DIAGNOSTIC - while ((pg = TAILQ_FIRST(&pmap->pm_obj.memq))) { + while ((pg = RB_ROOT(&pmap->pm_obj.memt))) { pt_entry_t *pde, *epde; struct vm_page *sheep; struct pv_entry *haggis; diff --git a/sys/arch/i386/i386/pmap.c b/sys/arch/i386/i386/pmap.c index 00cd9bf142d..a553b083971 100644 --- a/sys/arch/i386/i386/pmap.c +++ b/sys/arch/i386/i386/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.143 2009/07/25 12:55:39 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.144 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: pmap.c,v 1.91 2000/06/02 17:46:37 thorpej Exp $ */ /* @@ -805,7 +805,7 @@ pmap_bootstrap(vaddr_t kva_start) kpm = pmap_kernel(); simple_lock_init(&kpm->pm_obj.vmobjlock); kpm->pm_obj.pgops = NULL; - TAILQ_INIT(&kpm->pm_obj.memq); + RB_INIT(&kpm->pm_obj.memt); kpm->pm_obj.uo_npages = 0; kpm->pm_obj.uo_refs = 1; bzero(&kpm->pm_list, sizeof(kpm->pm_list)); /* pm_list not used */ @@ -1424,7 +1424,7 @@ pmap_drop_ptp(struct pmap *pm, vaddr_t va, struct vm_page *ptp, pm->pm_stats.resident_count--; /* update hint */ if (pm->pm_ptphint == ptp) - pm->pm_ptphint = TAILQ_FIRST(&pm->pm_obj.memq); + pm->pm_ptphint = RB_ROOT(&pm->pm_obj.memt); ptp->wire_count = 0; /* Postpone free to after shootdown. */ uvm_pagerealloc(ptp, NULL, 0); @@ -1461,7 +1461,7 @@ pmap_pinit(struct pmap *pmap) /* init uvm_object */ simple_lock_init(&pmap->pm_obj.vmobjlock); pmap->pm_obj.pgops = NULL; /* currently not a mappable object */ - TAILQ_INIT(&pmap->pm_obj.memq); + RB_INIT(&pmap->pm_obj.memt); pmap->pm_obj.uo_npages = 0; pmap->pm_obj.uo_refs = 1; pmap->pm_stats.wired_count = 0; @@ -1533,8 +1533,7 @@ pmap_destroy(struct pmap *pmap) simple_unlock(&pmaps_lock); /* Free any remaining PTPs. */ - while (!TAILQ_EMPTY(&pmap->pm_obj.memq)) { - pg = TAILQ_FIRST(&pmap->pm_obj.memq); + while ((pg = RB_ROOT(&pmap->pm_obj.memt)) != NULL) { pg->wire_count = 0; uvm_pagefree(pg); } @@ -2009,7 +2008,7 @@ pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags) /* If PTP is no longer being used, free it. */ if (ptp && ptp->wire_count <= 1) { pmap_drop_ptp(pmap, va, ptp, ptes); - TAILQ_INSERT_TAIL(&empty_ptps, ptp, listq); + TAILQ_INSERT_TAIL(&empty_ptps, ptp, pageq); } if (!shootall) @@ -2023,7 +2022,7 @@ pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags) pmap_unmap_ptes(pmap); PMAP_MAP_TO_HEAD_UNLOCK(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } @@ -2080,7 +2079,7 @@ pmap_page_remove(struct vm_page *pg) if (pve->pv_ptp && --pve->pv_ptp->wire_count <= 1) { pmap_drop_ptp(pve->pv_pmap, pve->pv_va, pve->pv_ptp, ptes); - TAILQ_INSERT_TAIL(&empty_ptps, pve->pv_ptp, listq); + TAILQ_INSERT_TAIL(&empty_ptps, pve->pv_ptp, pageq); } pmap_tlb_shootpage(pve->pv_pmap, pve->pv_va); @@ -2093,7 +2092,7 @@ pmap_page_remove(struct vm_page *pg) pmap_tlb_shootwait(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } diff --git a/sys/arch/i386/i386/pmapae.c b/sys/arch/i386/i386/pmapae.c index ed75721ad3c..8b17da23f22 100644 --- a/sys/arch/i386/i386/pmapae.c +++ b/sys/arch/i386/i386/pmapae.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmapae.c,v 1.19 2009/06/16 16:42:41 ariane Exp $ */ +/* $OpenBSD: pmapae.c,v 1.20 2009/08/06 15:28:14 oga Exp $ */ /* * Copyright (c) 2006 Michael Shalayeff @@ -1449,18 +1449,18 @@ pmap_remove_pae(struct pmap *pmap, vaddr_t sva, vaddr_t eva) pmap->pm_stats.resident_count--; if (pmap->pm_ptphint == ptp) pmap->pm_ptphint = - TAILQ_FIRST(&pmap->pm_obj.memq); + RB_ROOT(&pmap->pm_obj.memt); ptp->wire_count = 0; /* Postpone free to after shootdown. */ uvm_pagerealloc(ptp, NULL, 0); - TAILQ_INSERT_TAIL(&empty_ptps, ptp, listq); + TAILQ_INSERT_TAIL(&empty_ptps, ptp, pageq); } } pmap_tlb_shootnow(cpumask); pmap_unmap_ptes_pae(pmap); /* unlock pmap */ PMAP_MAP_TO_HEAD_UNLOCK(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } return; @@ -1542,11 +1542,11 @@ pmap_remove_pae(struct pmap *pmap, vaddr_t sva, vaddr_t eva) pmap->pm_stats.resident_count--; if (pmap->pm_ptphint == ptp) /* update hint? */ pmap->pm_ptphint = - TAILQ_FIRST(&pmap->pm_obj.memq); + RB_ROOT(&pmap->pm_obj.memt); ptp->wire_count = 0; /* Postpone free to after shootdown. */ uvm_pagerealloc(ptp, NULL, 0); - TAILQ_INSERT_TAIL(&empty_ptps, ptp, listq); + TAILQ_INSERT_TAIL(&empty_ptps, ptp, pageq); } } @@ -1554,7 +1554,7 @@ pmap_remove_pae(struct pmap *pmap, vaddr_t sva, vaddr_t eva) pmap_unmap_ptes_pae(pmap); PMAP_MAP_TO_HEAD_UNLOCK(); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } @@ -1660,12 +1660,12 @@ pmap_page_remove_pae(struct vm_page *pg) /* update hint? */ if (pve->pv_pmap->pm_ptphint == pve->pv_ptp) pve->pv_pmap->pm_ptphint = - TAILQ_FIRST(&pve->pv_pmap->pm_obj.memq); + RB_ROOT(&pve->pv_pmap->pm_obj.memt); pve->pv_ptp->wire_count = 0; /* Postpone free to after shootdown. */ uvm_pagerealloc(pve->pv_ptp, NULL, 0); TAILQ_INSERT_TAIL(&empty_ptps, pve->pv_ptp, - listq); + pageq); } } pmap_unmap_ptes_pae(pve->pv_pmap); /* unlocks pmap */ @@ -1676,7 +1676,7 @@ pmap_page_remove_pae(struct vm_page *pg) PMAP_HEAD_TO_MAP_UNLOCK(); pmap_tlb_shootnow(cpumask); while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) { - TAILQ_REMOVE(&empty_ptps, ptp, listq); + TAILQ_REMOVE(&empty_ptps, ptp, pageq); uvm_pagefree(ptp); } } diff --git a/sys/kern/vfs_biomem.c b/sys/kern/vfs_biomem.c index 89ab5f4d114..6b7aaa8d5e2 100644 --- a/sys/kern/vfs_biomem.c +++ b/sys/kern/vfs_biomem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_biomem.c,v 1.9 2009/06/25 15:49:26 thib Exp $ */ +/* $OpenBSD: vfs_biomem.c,v 1.10 2009/08/06 15:28:14 oga Exp $ */ /* * Copyright (c) 2007 Artur Grabowski <art@openbsd.org> * @@ -64,7 +64,7 @@ buf_mem_init(vsize_t size) buf_object = &buf_object_store; buf_object->pgops = NULL; - TAILQ_INIT(&buf_object->memq); + RB_INIT(&buf_object->memt); buf_object->uo_npages = 0; buf_object->uo_refs = 1; } diff --git a/sys/uvm/uvm_aobj.c b/sys/uvm/uvm_aobj.c index cc5a075e77f..4dd1c82e0a3 100644 --- a/sys/uvm/uvm_aobj.c +++ b/sys/uvm/uvm_aobj.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_aobj.c,v 1.46 2009/07/22 21:05:37 oga Exp $ */ +/* $OpenBSD: uvm_aobj.c,v 1.47 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_aobj.c,v 1.39 2001/02/18 21:19:08 chs Exp $ */ /* @@ -144,7 +144,7 @@ struct pool uao_swhash_elt_pool; */ struct uvm_aobj { - struct uvm_object u_obj; /* has: lock, pgops, memq, #pages, #refs */ + struct uvm_object u_obj; /* has: lock, pgops, memt, #pages, #refs */ int u_pages; /* number of pages in entire object */ int u_flags; /* the flags (see uvm_aobj.h) */ int *u_swslots; /* array of offset->swapslot mappings */ @@ -523,7 +523,7 @@ uao_create(vsize_t size, int flags) */ simple_lock_init(&aobj->u_obj.vmobjlock); aobj->u_obj.pgops = &aobj_pager; - TAILQ_INIT(&aobj->u_obj.memq); + RB_INIT(&aobj->u_obj.memt); aobj->u_obj.uo_npages = 0; /* @@ -667,7 +667,7 @@ uao_detach_locked(struct uvm_object *uobj) * Release swap resources then free the page. */ uvm_lock_pageq(); - while((pg = TAILQ_FIRST(&uobj->memq)) != NULL) { + while((pg = RB_ROOT(&uobj->memt)) != NULL) { if (pg->pg_flags & PG_BUSY) { atomic_setbits_int(&pg->pg_flags, PG_WANTED); uvm_unlock_pageq(); @@ -702,11 +702,6 @@ uao_detach_locked(struct uvm_object *uobj) * or block. * => if PGO_ALLPAGE is set, then all pages in the object are valid targets * for flushing. - * => NOTE: we rely on the fact that the object's memq is a TAILQ and - * that new pages are inserted on the tail end of the list. thus, - * we can make a complete pass through the object in one go by starting - * at the head and working towards the tail (new pages are put in - * front of us). * => NOTE: we are allowed to lock the page queues, so the caller * must not be holding the lock on them [e.g. pagedaemon had * better not call us with the queues locked] diff --git a/sys/uvm/uvm_device.c b/sys/uvm/uvm_device.c index 53b28c095e5..27e079934b3 100644 --- a/sys/uvm/uvm_device.c +++ b/sys/uvm/uvm_device.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_device.c,v 1.35 2009/06/16 23:54:57 oga Exp $ */ +/* $OpenBSD: uvm_device.c,v 1.36 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_device.c,v 1.30 2000/11/25 06:27:59 chs Exp $ */ /* @@ -245,7 +245,7 @@ udv_attach(void *arg, vm_prot_t accessprot, voff_t off, vsize_t size) simple_lock_init(&udv->u_obj.vmobjlock); udv->u_obj.pgops = &uvm_deviceops; - TAILQ_INIT(&udv->u_obj.memq); + RB_INIT(&udv->u_obj.memt); udv->u_obj.uo_npages = 0; udv->u_obj.uo_refs = 1; udv->u_flags = 0; @@ -305,7 +305,7 @@ again: uobj,uobj->uo_refs,0,0); return; } - KASSERT(uobj->uo_npages == 0 && TAILQ_EMPTY(&uobj->memq)); + KASSERT(uobj->uo_npages == 0 && RB_EMPTY(&uobj->memt)); /* * is it being held? if so, wait until others are done. diff --git a/sys/uvm/uvm_init.c b/sys/uvm/uvm_init.c index 76931227928..69502ec87b3 100644 --- a/sys/uvm/uvm_init.c +++ b/sys/uvm/uvm_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_init.c,v 1.24 2009/06/16 23:54:58 oga Exp $ */ +/* $OpenBSD: uvm_init.c,v 1.25 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_init.c,v 1.14 2000/06/27 17:29:23 mrg Exp $ */ /* @@ -143,12 +143,10 @@ uvm_init(void) uvm_km_page_init(); /* - * the VM system is now up! now that malloc is up we can resize the - * <obj,off> => <page> hash table for general use and enable paging - * of kernel objects. + * the VM system is now up! now that malloc is up we can + * enable paging of kernel objects. */ - uvm_page_rehash(); uao_create(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS, UAO_FLAG_KERNSWAP); diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index 1710efb09a3..e418e9bbeb6 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_map.c,v 1.119 2009/07/25 12:55:40 miod Exp $ */ +/* $OpenBSD: uvm_map.c,v 1.120 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */ /* @@ -3823,13 +3823,12 @@ uvm_object_printit(uobj, full, pr) return; } (*pr)(" PAGES <pg,offset>:\n "); - for (pg = TAILQ_FIRST(&uobj->memq); - pg != NULL; - pg = TAILQ_NEXT(pg, listq), cnt++) { + RB_FOREACH(pg, uvm_objtree, &uobj->memt) { (*pr)("<%p,0x%llx> ", pg, (long long)pg->offset); if ((cnt % 3) == 2) { (*pr)("\n "); } + cnt++; } if ((cnt % 3) != 2) { (*pr)("\n"); @@ -3886,7 +3885,7 @@ uvm_page_printit(pg, full, pr) uobj = pg->uobject; if (uobj) { (*pr)(" checking object list\n"); - TAILQ_FOREACH(tpg, &uobj->memq, listq) { + RB_FOREACH(tpg, uvm_objtree, &uobj->memt) { if (tpg == pg) { break; } diff --git a/sys/uvm/uvm_object.h b/sys/uvm/uvm_object.h index 44a16bfd7c1..b1b9366fe57 100644 --- a/sys/uvm/uvm_object.h +++ b/sys/uvm/uvm_object.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_object.h,v 1.14 2009/06/17 00:13:59 oga Exp $ */ +/* $OpenBSD: uvm_object.h,v 1.15 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_object.h,v 1.11 2001/03/09 01:02:12 chs Exp $ */ /* @@ -47,11 +47,11 @@ */ struct uvm_object { - simple_lock_data_t vmobjlock; /* lock on memq */ - struct uvm_pagerops *pgops; /* pager ops */ - struct pglist memq; /* pages in this object */ - int uo_npages; /* # of pages in memq */ - int uo_refs; /* reference count */ + simple_lock_data_t vmobjlock; /* lock on memt */ + struct uvm_pagerops *pgops; /* pager ops */ + RB_HEAD(uvm_objtree, vm_page) memt; /* pages in object */ + int uo_npages; /* # of pages in memt */ + int uo_refs; /* reference count */ }; /* @@ -83,6 +83,10 @@ struct uvm_object { extern struct uvm_pagerops uvm_vnodeops; extern struct uvm_pagerops uvm_deviceops; +/* For object trees */ +int uvm_pagecmp(struct vm_page *, struct vm_page *); +RB_PROTOTYPE(uvm_objtree, vm_page, objt, uvm_pagecmp) + #define UVM_OBJ_IS_VNODE(uobj) \ ((uobj)->pgops == &uvm_vnodeops) diff --git a/sys/uvm/uvm_page.c b/sys/uvm/uvm_page.c index 76ca752bea1..2faa524de07 100644 --- a/sys/uvm/uvm_page.c +++ b/sys/uvm/uvm_page.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_page.c,v 1.94 2009/07/26 21:26:10 deraadt Exp $ */ +/* $OpenBSD: uvm_page.c,v 1.95 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_page.c,v 1.44 2000/11/27 08:40:04 chs Exp $ */ /* @@ -82,6 +82,17 @@ #include <uvm/uvm.h> /* + * for object trees + */ +RB_GENERATE(uvm_objtree, vm_page, objt, uvm_pagecmp); + +int +uvm_pagecmp(struct vm_page *a, struct vm_page *b) +{ + return (a->offset < b->offset ? -1 : a->offset > b->offset); +} + +/* * global vars... XXXCDC: move to uvm. structure. */ @@ -118,14 +129,6 @@ static vaddr_t virtual_space_start; static vaddr_t virtual_space_end; /* - * we use a hash table with only one bucket during bootup. we will - * later rehash (resize) the hash table once the allocator is ready. - * we static allocate the one bootstrap bucket below... - */ - -static struct pglist uvm_bootbucket; - -/* * History */ UVMHIST_DECL(pghist); @@ -142,10 +145,10 @@ static void uvm_pageremove(struct vm_page *); */ /* - * uvm_pageinsert: insert a page in the object and the hash table + * uvm_pageinsert: insert a page in the object * * => caller must lock object - * => caller must lock page queues + * => caller must lock page queues XXX questionable * => call should have already set pg's object and offset pointers * and bumped the version counter */ @@ -153,22 +156,17 @@ static void uvm_pageremove(struct vm_page *); __inline static void uvm_pageinsert(struct vm_page *pg) { - struct pglist *buck; UVMHIST_FUNC("uvm_pageinsert"); UVMHIST_CALLED(pghist); KASSERT((pg->pg_flags & PG_TABLED) == 0); - mtx_enter(&uvm.hashlock); - buck = &uvm.page_hash[uvm_pagehash(pg->uobject,pg->offset)]; - TAILQ_INSERT_TAIL(buck, pg, hashq); /* put in hash */ - mtx_leave(&uvm.hashlock); - - TAILQ_INSERT_TAIL(&pg->uobject->memq, pg, listq); /* put in object */ + /* XXX should we check duplicates? */ + RB_INSERT(uvm_objtree, &pg->uobject->memt, pg); atomic_setbits_int(&pg->pg_flags, PG_TABLED); pg->uobject->uo_npages++; } /* - * uvm_page_remove: remove page from object and hash + * uvm_page_remove: remove page from object * * => caller must lock object * => caller must lock page queues @@ -177,23 +175,10 @@ uvm_pageinsert(struct vm_page *pg) static __inline void uvm_pageremove(struct vm_page *pg) { - struct pglist *buck; UVMHIST_FUNC("uvm_pageremove"); UVMHIST_CALLED(pghist); KASSERT(pg->pg_flags & PG_TABLED); - mtx_enter(&uvm.hashlock); - buck = &uvm.page_hash[uvm_pagehash(pg->uobject,pg->offset)]; - TAILQ_REMOVE(buck, pg, hashq); - mtx_leave(&uvm.hashlock); - -#ifdef UBC - if (pg->uobject->pgops == &uvm_vnodeops) { - uvm_pgcnt_vnode--; - } -#endif - - /* object should be locked */ - TAILQ_REMOVE(&pg->uobject->memq, pg, listq); + RB_REMOVE(uvm_objtree, &pg->uobject->memt, pg); atomic_clearbits_int(&pg->pg_flags, PG_TABLED); pg->uobject->uo_npages--; @@ -236,18 +221,6 @@ uvm_page_init(vaddr_t *kvm_startp, vaddr_t *kvm_endp) simple_lock_init(&uvm.pageqlock); mtx_init(&uvm.fpageqlock, IPL_VM); - /* - * init the <obj,offset> => <page> hash table. for now - * we just have one bucket (the bootstrap bucket). later on we - * will allocate new buckets as we dynamically resize the hash table. - */ - - uvm.page_nhash = 1; /* 1 bucket */ - uvm.page_hashmask = 0; /* mask for hash function */ - uvm.page_hash = &uvm_bootbucket; /* install bootstrap bucket */ - TAILQ_INIT(uvm.page_hash); /* init hash table */ - mtx_init(&uvm.hashlock, IPL_VM); /* init hash table lock */ - /* * allocate vm_page structures. */ @@ -742,97 +715,9 @@ uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, * done! */ - if (!preload) - uvm_page_rehash(); - - return; -} - -/* - * uvm_page_rehash: reallocate hash table based on number of free pages. - */ - -void -uvm_page_rehash(void) -{ - int freepages, lcv, bucketcount, oldcount; - struct pglist *newbuckets, *oldbuckets; - struct vm_page *pg; - size_t newsize, oldsize; - - /* - * compute number of pages that can go in the free pool - */ - - freepages = 0; - for (lcv = 0 ; lcv < vm_nphysseg ; lcv++) - freepages += - (vm_physmem[lcv].avail_end - vm_physmem[lcv].avail_start); - - /* - * compute number of buckets needed for this number of pages - */ - - bucketcount = 1; - while (bucketcount < freepages) - bucketcount = bucketcount * 2; - - /* - * compute the size of the current table and new table. - */ - - oldbuckets = uvm.page_hash; - oldcount = uvm.page_nhash; - oldsize = round_page(sizeof(struct pglist) * oldcount); - newsize = round_page(sizeof(struct pglist) * bucketcount); - - /* - * allocate the new buckets - */ - - newbuckets = (struct pglist *) uvm_km_alloc(kernel_map, newsize); - if (newbuckets == NULL) { - printf("uvm_page_physrehash: WARNING: could not grow page " - "hash table\n"); - return; - } - for (lcv = 0 ; lcv < bucketcount ; lcv++) - TAILQ_INIT(&newbuckets[lcv]); - - /* - * now replace the old buckets with the new ones and rehash everything - */ - - mtx_enter(&uvm.hashlock); - uvm.page_hash = newbuckets; - uvm.page_nhash = bucketcount; - uvm.page_hashmask = bucketcount - 1; /* power of 2 */ - - /* ... and rehash */ - for (lcv = 0 ; lcv < oldcount ; lcv++) { - while ((pg = TAILQ_FIRST(&oldbuckets[lcv])) != NULL) { - TAILQ_REMOVE(&oldbuckets[lcv], pg, hashq); - TAILQ_INSERT_TAIL( - &uvm.page_hash[uvm_pagehash(pg->uobject, pg->offset)], - pg, hashq); - } - } - mtx_leave(&uvm.hashlock); - - /* - * free old bucket array if is not the boot-time table - */ - - if (oldbuckets != &uvm_bootbucket) - uvm_km_free(kernel_map, (vaddr_t) oldbuckets, oldsize); - - /* - * done - */ return; } - #ifdef DDB /* XXXCDC: TMP TMP TMP DEBUG DEBUG DEBUG */ void uvm_page_physdump(void); /* SHUT UP GCC */ @@ -843,8 +728,8 @@ uvm_page_physdump(void) { int lcv; - printf("rehash: physical memory config [segs=%d of %d]:\n", - vm_nphysseg, VM_PHYSSEG_MAX); + printf("uvm_page_physdump: physical memory config [segs=%d of %d]:\n", + vm_nphysseg, VM_PHYSSEG_MAX); for (lcv = 0 ; lcv < vm_nphysseg ; lcv++) printf("0x%llx->0x%llx [0x%llx->0x%llx]\n", (long long)vm_physmem[lcv].start, @@ -858,7 +743,6 @@ uvm_page_physdump(void) case VM_PSTRAT_BIGFIRST: printf("BIGFIRST\n"); break; default: printf("<<UNKNOWN>>!!!!\n"); } - printf("number of buckets = %d\n", uvm.page_nhash); } #endif @@ -875,7 +759,7 @@ uvm_shutdown(void) * * => return null if no pages free * => wake up pagedaemon if number of free pages drops below low water mark - * => if obj != NULL, obj must be locked (to put in hash) + * => if obj != NULL, obj must be locked (to put in tree) * => if anon != NULL, anon must be locked (to put in anon) * => only one of obj or anon can be non-null * => caller must activate/deactivate page if it is not wired. @@ -1090,7 +974,7 @@ uvm_pagerealloc(struct vm_page *pg, struct uvm_object *newobj, voff_t newoff) /* * uvm_pagefree: free page * - * => erase page's identity (i.e. remove from hash/object) + * => erase page's identity (i.e. remove from object) * => put page on free list * => caller must lock owning object (either anon or uvm_object) * => caller must lock page queues @@ -1475,19 +1359,11 @@ PHYS_TO_VM_PAGE(paddr_t pa) struct vm_page * uvm_pagelookup(struct uvm_object *obj, voff_t off) { - struct vm_page *pg; - struct pglist *buck; - - mtx_enter(&uvm.hashlock); - buck = &uvm.page_hash[uvm_pagehash(obj,off)]; + /* XXX if stack is too much, handroll */ + struct vm_page pg; - TAILQ_FOREACH(pg, buck, hashq) { - if (pg->uobject == obj && pg->offset == off) { - break; - } - } - mtx_leave(&uvm.hashlock); - return(pg); + pg.offset = off; + return (RB_FIND(uvm_objtree, &obj->memt, &pg)); } /* diff --git a/sys/uvm/uvm_page.h b/sys/uvm/uvm_page.h index 366535db35c..531ff9d0fcd 100644 --- a/sys/uvm/uvm_page.h +++ b/sys/uvm/uvm_page.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_page.h,v 1.39 2009/06/17 00:13:59 oga Exp $ */ +/* $OpenBSD: uvm_page.h,v 1.40 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_page.h,v 1.19 2000/12/28 08:24:55 chs Exp $ */ /* @@ -83,16 +83,8 @@ * * A small structure is kept for each resident * page, indexed by page number. Each structure - * is an element of several lists: - * - * A hash table bucket used to quickly - * perform object/offset lookups - * - * A list of all pages for a given object, - * so they can be quickly deactivated at - * time of deallocation. - * - * An ordered list of pages due for pageout. + * contains a list used for manipulating pages, and + * a tree structure for in object/offset lookups * * In addition, the structure contains the object * and offset to which this page belongs (for pageout), @@ -109,8 +101,7 @@ struct vm_page { TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO * queue or free list (P) */ - TAILQ_ENTRY(vm_page) hashq; /* hash table links (O)*/ - TAILQ_ENTRY(vm_page) listq; /* pages in same object (O)*/ + RB_ENTRY(vm_page) objt; /* object tree (O)*/ struct vm_anon *uanon; /* anon (O,P) */ struct uvm_object *uobject; /* object (O,P) */ @@ -242,7 +233,6 @@ void uvm_page_own(struct vm_page *, char *); #if !defined(PMAP_STEAL_MEMORY) boolean_t uvm_page_physget(paddr_t *); #endif -void uvm_page_rehash(void); void uvm_pageidlezero(void); void uvm_pageactivate(struct vm_page *); @@ -309,9 +299,6 @@ int vm_physseg_find(paddr_t, int *); #define uvm_lock_fpageq() mtx_enter(&uvm.fpageqlock); #define uvm_unlock_fpageq() mtx_leave(&uvm.fpageqlock); -#define uvm_pagehash(obj,off) \ - (((unsigned long)obj+(unsigned long)atop(off)) & uvm.page_hashmask) - #define UVM_PAGEZERO_TARGET (uvmexp.free) #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) diff --git a/sys/uvm/uvm_vnode.c b/sys/uvm/uvm_vnode.c index 15130e95ded..207237eb3a4 100644 --- a/sys/uvm/uvm_vnode.c +++ b/sys/uvm/uvm_vnode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_vnode.c,v 1.68 2009/07/22 21:05:37 oga Exp $ */ +/* $OpenBSD: uvm_vnode.c,v 1.69 2009/08/06 15:28:14 oga Exp $ */ /* $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $ */ /* @@ -271,7 +271,7 @@ uvn_attach(void *arg, vm_prot_t accessprot) * now set up the uvn. */ uvn->u_obj.pgops = &uvm_vnodeops; - TAILQ_INIT(&uvn->u_obj.memq); + RB_INIT(&uvn->u_obj.memt); uvn->u_obj.uo_npages = 0; uvn->u_obj.uo_refs = 1; /* just us... */ oldflags = uvn->u_flags; @@ -438,11 +438,7 @@ uvn_detach(struct uvm_object *uobj) if (uvn->u_flags & UVM_VNODE_WRITEABLE) { LIST_REMOVE(uvn, u_wlist); } -#ifdef DIAGNOSTIC - if (!TAILQ_EMPTY(&uobj->memq)) - panic("uvn_deref: vnode VM object still has pages afer " - "syncio/free flush"); -#endif + KASSERT(RB_EMPTY(&uobj->memt)); oldflags = uvn->u_flags; uvn->u_flags = 0; simple_unlock(&uobj->vmobjlock); @@ -559,7 +555,7 @@ uvm_vnp_terminate(struct vnode *vp) while (uvn->u_obj.uo_npages) { #ifdef DEBUG struct vm_page *pp; - TAILQ_FOREACH(pp, &uvn->u_obj.memq, listq) { + RB_FOREACH(pp, uvm_objtree, &uvn->u_obj.memt) { if ((pp->pg_flags & PG_BUSY) == 0) panic("uvm_vnp_terminate: detected unbusy pg"); } @@ -669,11 +665,6 @@ uvm_vnp_terminate(struct vnode *vp) * or block. * => if PGO_ALLPAGE is set, then all pages in the object are valid targets * for flushing. - * => NOTE: we rely on the fact that the object's memq is a TAILQ and - * that new pages are inserted on the tail end of the list. thus, - * we can make a complete pass through the object in one go by starting - * at the head and working towards the tail (new pages are put in - * front of us). * => NOTE: we are allowed to lock the page queues, so the caller * must not be holding the lock on them [e.g. pagedaemon had * better not call us with the queues locked] @@ -692,19 +683,6 @@ uvm_vnp_terminate(struct vnode *vp) * object we need to wait for the other PG_BUSY pages to clear * off (i.e. we need to do an iosync). also note that once a * page is PG_BUSY it must stay in its object until it is un-busyed. - * - * note on page traversal: - * we can traverse the pages in an object either by going down the - * linked list in "uobj->memq", or we can go over the address range - * by page doing hash table lookups for each address. depending - * on how many pages are in the object it may be cheaper to do one - * or the other. we set "by_list" to true if we are using memq. - * if the cost of a hash lookup was equal to the cost of the list - * traversal we could compare the number of pages in the start->stop - * range to the total number of pages in the object. however, it - * seems that a hash table lookup is more expensive than the linked - * list traversal, so we multiply the number of pages in the - * start->stop range by a penalty which we define below. */ #define UVN_HASH_PENALTY 4 /* XXX: a guess */ |