diff options
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/device_pager.c | 8 | ||||
-rw-r--r-- | sys/vm/swap_pager.c | 44 | ||||
-rw-r--r-- | sys/vm/vm_fault.c | 24 | ||||
-rw-r--r-- | sys/vm/vm_glue.c | 104 | ||||
-rw-r--r-- | sys/vm/vm_kern.c | 29 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 243 | ||||
-rw-r--r-- | sys/vm/vm_meter.c | 10 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 5 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 85 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 369 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 139 | ||||
-rw-r--r-- | sys/vm/vm_pager.c | 8 |
12 files changed, 474 insertions, 594 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 8b1ddf2..514b471 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)device_pager.c 8.1 (Berkeley) 6/11/93 - * $Id: device_pager.c,v 1.21 1996/03/09 06:54:41 dyson Exp $ + * $Id: device_pager.c,v 1.22 1996/05/03 21:01:45 phk Exp $ */ #include <sys/param.h> @@ -182,7 +182,7 @@ dev_pager_dealloc(object) /* * Free up our fake pages. */ - while ((m = object->un_pager.devp.devp_pglist.tqh_first) != 0) { + while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) != 0) { TAILQ_REMOVE(&object->un_pager.devp.devp_pglist, m, pageq); dev_pager_putfake(m); } @@ -265,14 +265,14 @@ dev_pager_getfake(paddr) vm_page_t m; int i; - if (dev_pager_fakelist.tqh_first == NULL) { + if (TAILQ_FIRST(&dev_pager_fakelist) == NULL) { m = (vm_page_t) malloc(PAGE_SIZE * 2, M_VMPGDATA, M_WAITOK); for (i = (PAGE_SIZE * 2) / sizeof(*m); i > 0; i--) { TAILQ_INSERT_TAIL(&dev_pager_fakelist, m, pageq); m++; } } - m = dev_pager_fakelist.tqh_first; + m = TAILQ_FIRST(&dev_pager_fakelist); TAILQ_REMOVE(&dev_pager_fakelist, m, pageq); m->flags = PG_BUSY | PG_FICTITIOUS; diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index b6c7db6..4feebd5 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -39,7 +39,7 @@ * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ * * @(#)swap_pager.c 8.9 (Berkeley) 3/21/94 - * $Id: swap_pager.c,v 1.64 1996/05/02 14:21:14 phk Exp $ + * $Id: swap_pager.c,v 1.65 1996/05/03 21:01:47 phk Exp $ */ /* @@ -530,7 +530,7 @@ swap_pager_reclaim() /* for each pager queue */ for (k = 0; swp_qs[k]; k++) { - object = swp_qs[k]->tqh_first; + object = TAILQ_FIRST(swp_qs[k]); while (object && (reclaimcount < MAXRECLAIM)) { /* @@ -555,7 +555,7 @@ swap_pager_reclaim() } } } - object = object->pager_object_list.tqe_next; + object = TAILQ_NEXT(object, pager_object_list); } } @@ -956,8 +956,8 @@ swap_pager_getpages(object, m, count, reqpage) spc = NULL; /* we might not use an spc data structure */ - if ((count == 1) && (swap_pager_free.tqh_first != NULL)) { - spc = swap_pager_free.tqh_first; + if ((count == 1) && (TAILQ_FIRST(&swap_pager_free) != NULL)) { + spc = TAILQ_FIRST(&swap_pager_free); TAILQ_REMOVE(&swap_pager_free, spc, spc_list); kva = spc->spc_kva; bp = spc->spc_bp; @@ -1263,9 +1263,9 @@ swap_pager_putpages(object, m, count, sync, rtvals) /* * get a swap pager clean data structure, block until we get it */ - if (swap_pager_free.tqh_first == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { + if (TAILQ_FIRST(&swap_pager_free) == NULL || + TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list) == NULL || + TAILQ_NEXT(TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list),spc_list) == NULL) { s = splbio(); if (curproc == pageproc) { retryfree: @@ -1285,9 +1285,9 @@ retryfree: */ if (tsleep(&swap_pager_free, PVM, "swpfre", hz/5)) { swap_pager_sync(); - if (swap_pager_free.tqh_first == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { + if (TAILQ_FIRST(&swap_pager_free) == NULL || + TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list) == NULL || + TAILQ_NEXT(TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list),spc_list) == NULL) { splx(s); return VM_PAGER_AGAIN; } @@ -1297,17 +1297,17 @@ retryfree: * the free swap control blocks. */ swap_pager_sync(); - if (swap_pager_free.tqh_first == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { + if (TAILQ_FIRST(&swap_pager_free) == NULL || + TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list) == NULL || + TAILQ_NEXT(TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list),spc_list) == NULL) { goto retryfree; } } } else { pagedaemon_wakeup(); - while (swap_pager_free.tqh_first == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next == NULL || - swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { + while (TAILQ_FIRST(&swap_pager_free) == NULL || + TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list) == NULL || + TAILQ_NEXT(TAILQ_NEXT(TAILQ_FIRST(&swap_pager_free),spc_list),spc_list) == NULL) { swap_pager_needflags |= SWAP_FREE_NEEDED; tsleep(&swap_pager_free, PVM, "swpfre", 0); pagedaemon_wakeup(); @@ -1315,7 +1315,7 @@ retryfree: } splx(s); } - spc = swap_pager_free.tqh_first; + spc = TAILQ_FIRST(&swap_pager_free); TAILQ_REMOVE(&swap_pager_free, spc, spc_list); kva = spc->spc_kva; @@ -1482,7 +1482,7 @@ swap_pager_sync() register int s; tspc = NULL; - if (swap_pager_done.tqh_first == NULL) + if (TAILQ_FIRST(&swap_pager_done) == NULL) return; for (;;) { s = splbio(); @@ -1490,7 +1490,7 @@ swap_pager_sync() * Look up and removal from done list must be done at splbio() * to avoid conflicts with swap_pager_iodone. */ - while ((spc = swap_pager_done.tqh_first) != 0) { + while ((spc = TAILQ_FIRST(&swap_pager_done)) != 0) { pmap_qremove(spc->spc_kva, spc->spc_count); swap_pager_finish(spc); TAILQ_REMOVE(&swap_pager_done, spc, spc_list); @@ -1609,7 +1609,7 @@ swap_pager_iodone(bp) wakeup(spc->spc_object); } if ((swap_pager_needflags & SWAP_FREE_NEEDED) || - swap_pager_inuse.tqh_first == 0) { + TAILQ_FIRST(&swap_pager_inuse) == 0) { swap_pager_needflags &= ~SWAP_FREE_NEEDED; wakeup(&swap_pager_free); } @@ -1623,7 +1623,7 @@ swap_pager_iodone(bp) wakeup(&vm_pageout_pages_needed); vm_pageout_pages_needed = 0; } - if ((swap_pager_inuse.tqh_first == NULL) || + if ((TAILQ_FIRST(&swap_pager_inuse) == NULL) || ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min && nswiodone + cnt.v_free_count + cnt.v_cache_count >= cnt.v_free_min)) { pagedaemon_wakeup(); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index e9f8f16..904270b 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -66,7 +66,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_fault.c,v 1.42 1996/03/09 06:48:26 dyson Exp $ + * $Id: vm_fault.c,v 1.43 1996/03/28 04:53:23 dyson Exp $ */ /* @@ -269,8 +269,8 @@ RetryFault:; int s; UNLOCK_THINGS; - s = splhigh(); - if ((m->flags & PG_BUSY) || m->busy) { + s = splvm(); + if (((m->flags & PG_BUSY) || m->busy)) { m->flags |= PG_WANTED | PG_REFERENCED; cnt.v_intrans++; tsleep(m, PSWP, "vmpfw", 0); @@ -311,7 +311,7 @@ RetryFault:; * Allocate a new page for this object/offset pair. */ m = vm_page_alloc(object, pindex, - vp?VM_ALLOC_NORMAL:VM_ALLOC_ZERO); + (vp || object->backing_object)?VM_ALLOC_NORMAL:VM_ALLOC_ZERO); if (m == NULL) { UNLOCK_AND_DEALLOCATE; @@ -551,9 +551,9 @@ readrest: vm_pindex_t other_pindex, other_pindex_offset; vm_page_t tm; - other_object = object->shadow_head.tqh_first; + other_object = TAILQ_FIRST(&object->shadow_head); if (other_object == first_object) - other_object = other_object->shadow_list.tqe_next; + other_object = TAILQ_NEXT(other_object, shadow_list); if (!other_object) panic("vm_fault: other object missing"); if (other_object && @@ -712,7 +712,7 @@ readrest: m->valid = VM_PAGE_BITS_ALL; pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), prot, wired); - if (vp && (change_wiring == 0) && (wired == 0)) + if ((change_wiring == 0) && (wired == 0)) pmap_prefault(map->pmap, vaddr, entry, first_object); /* @@ -780,8 +780,9 @@ vm_fault_wire(map, start, end) for (va = start; va < end; va += PAGE_SIZE) { while( curproc != pageproc && - (cnt.v_free_count <= cnt.v_pageout_free_min)) + (cnt.v_free_count <= cnt.v_pageout_free_min)) { VM_WAIT; + } rv = vm_fault(map, va, VM_PROT_READ|VM_PROT_WRITE, TRUE); if (rv) { @@ -817,11 +818,10 @@ vm_fault_unwire(map, start, end) for (va = start; va < end; va += PAGE_SIZE) { pa = pmap_extract(pmap, va); - if (pa == (vm_offset_t) 0) { - panic("unwire: page not in pmap"); + if (pa != (vm_offset_t) 0) { + pmap_change_wiring(pmap, va, FALSE); + vm_page_unwire(PHYS_TO_VM_PAGE(pa)); } - pmap_change_wiring(pmap, va, FALSE); - vm_page_unwire(PHYS_TO_VM_PAGE(pa)); } /* diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 4e6db8c..8e09433 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -59,7 +59,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_glue.c,v 1.47 1996/04/09 04:36:58 dyson Exp $ + * $Id: vm_glue.c,v 1.48 1996/05/02 09:34:51 phk Exp $ */ #include "opt_ddb.h" @@ -196,16 +196,15 @@ vm_fork(p1, p2) register struct proc *p1, *p2; { register struct user *up; - vm_offset_t addr, ptaddr, ptpa; int error, i; - vm_map_t map; pmap_t pvp; - vm_page_t stkm; + vm_object_t upobj; while ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min) { VM_WAIT; } +#if 0 /* * avoid copying any of the parent's pagetables or other per-process * objects that reside in the map by marking all of them @@ -213,6 +212,7 @@ vm_fork(p1, p2) */ (void) vm_map_inherit(&p1->p_vmspace->vm_map, UPT_MIN_ADDRESS - UPAGES * PAGE_SIZE, VM_MAX_ADDRESS, VM_INHERIT_NONE); +#endif p2->p_vmspace = vmspace_fork(p1->p_vmspace); if (p1->p_vmspace->vm_shm) @@ -223,61 +223,26 @@ vm_fork(p1, p2) * process */ - addr = (vm_offset_t) kstack; - - map = &p2->p_vmspace->vm_map; pvp = &p2->p_vmspace->vm_pmap; /* * allocate object for the upages */ - p2->p_vmspace->vm_upages_obj = vm_object_allocate( OBJT_DEFAULT, + p2->p_vmspace->vm_upages_obj = upobj = vm_object_allocate( OBJT_DEFAULT, UPAGES); - /* - * put upages into the address space - */ - error = vm_map_find(map, p2->p_vmspace->vm_upages_obj, 0, - &addr, UPT_MIN_ADDRESS - addr, FALSE, VM_PROT_ALL, - VM_PROT_ALL, 0); - if (error != KERN_SUCCESS) - panic("vm_fork: vm_map_find (UPAGES) failed, addr=0x%x, error=%d", addr, error); - - addr += UPAGES * PAGE_SIZE; - /* allocate space for page tables */ - error = vm_map_find(map, NULL, 0, &addr, UPT_MAX_ADDRESS - addr, FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error != KERN_SUCCESS) - panic("vm_fork: vm_map_find (PTES) failed, addr=0x%x, error=%d", addr, error); - /* get a kernel virtual address for the UPAGES for this proc */ up = (struct user *) kmem_alloc_pageable(u_map, UPAGES * PAGE_SIZE); if (up == NULL) panic("vm_fork: u_map allocation failed"); - /* - * create a pagetable page for the UPAGES in the process address space - */ - ptaddr = trunc_page((u_int) vtopte(kstack)); - (void) vm_fault(map, ptaddr, VM_PROT_READ|VM_PROT_WRITE, FALSE); - ptpa = pmap_extract(pvp, ptaddr); - if (ptpa == 0) { - panic("vm_fork: no pte for UPAGES"); - } - - /* - * hold the page table page for the kernel stack, and fault them in - */ - stkm = PHYS_TO_VM_PAGE(ptpa); - vm_page_hold(stkm); - for(i=0;i<UPAGES;i++) { vm_page_t m; /* * Get a kernel stack page */ - while ((m = vm_page_alloc(p2->p_vmspace->vm_upages_obj, + while ((m = vm_page_alloc(upobj, i, VM_ALLOC_NORMAL)) == NULL) { VM_WAIT; } @@ -286,24 +251,20 @@ vm_fork(p1, p2) * Wire the page */ vm_page_wire(m); - m->flags &= ~PG_BUSY; + PAGE_WAKEUP(m); /* * Enter the page into both the kernel and the process * address space. */ pmap_enter( pvp, (vm_offset_t) kstack + i * PAGE_SIZE, - VM_PAGE_TO_PHYS(m), VM_PROT_READ|VM_PROT_WRITE, 1); + VM_PAGE_TO_PHYS(m), VM_PROT_READ|VM_PROT_WRITE, TRUE); pmap_kenter(((vm_offset_t) up) + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m)); m->flags &= ~PG_ZERO; + m->flags |= PG_MAPPED; m->valid = VM_PAGE_BITS_ALL; } - /* - * The page table page for the kernel stack should be held in memory - * now. - */ - vm_page_unhold(stkm); p2->p_addr = up; @@ -371,33 +332,22 @@ faultin(p) int s; if ((p->p_flag & P_INMEM) == 0) { - vm_map_t map = &p->p_vmspace->vm_map; pmap_t pmap = &p->p_vmspace->vm_pmap; vm_page_t stkm, m; - vm_offset_t ptpa; int error; + vm_object_t upobj = p->p_vmspace->vm_upages_obj; ++p->p_lock; #if defined(SWAP_DEBUG) printf("swapping in %d\n", p->p_pid); #endif - ptaddr = trunc_page((u_int) vtopte(kstack)); - (void) vm_fault(map, ptaddr, VM_PROT_READ|VM_PROT_WRITE, FALSE); - ptpa = pmap_extract(&p->p_vmspace->vm_pmap, ptaddr); - if (ptpa == 0) { - panic("vm_fork: no pte for UPAGES"); - } - stkm = PHYS_TO_VM_PAGE(ptpa); - vm_page_hold(stkm); - for(i=0;i<UPAGES;i++) { int s; - s = splhigh(); - + s = splvm(); retry: - if ((m = vm_page_lookup(p->p_vmspace->vm_upages_obj, i)) == NULL) { - if ((m = vm_page_alloc(p->p_vmspace->vm_upages_obj, i, VM_ALLOC_NORMAL)) == NULL) { + if ((m = vm_page_lookup(upobj, i)) == NULL) { + if ((m = vm_page_alloc(upobj, i, VM_ALLOC_NORMAL)) == NULL) { VM_WAIT; goto retry; } @@ -407,10 +357,9 @@ retry: tsleep(m, PVM, "swinuw",0); goto retry; } + m->flags |= PG_BUSY; } vm_page_wire(m); - if (m->valid == VM_PAGE_BITS_ALL) - m->flags &= ~PG_BUSY; splx(s); pmap_enter( pmap, (vm_offset_t) kstack + i * PAGE_SIZE, @@ -419,16 +368,15 @@ retry: VM_PAGE_TO_PHYS(m)); if (m->valid != VM_PAGE_BITS_ALL) { int rv; - rv = vm_pager_get_pages(p->p_vmspace->vm_upages_obj, + rv = vm_pager_get_pages(upobj, &m, 1, 0); if (rv != VM_PAGER_OK) panic("faultin: cannot get upages for proc: %d\n", p->p_pid); m->valid = VM_PAGE_BITS_ALL; - m->flags &= ~PG_BUSY; } + PAGE_WAKEUP(m); + m->flags |= PG_MAPPED; } - vm_page_unhold(stkm); - s = splhigh(); @@ -527,8 +475,12 @@ swapout_procs() outpri = outpri2 = INT_MIN; retry: for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { + struct vmspace *vm; if (!swappable(p)) continue; + + vm = p->p_vmspace; + switch (p->p_stat) { default: continue; @@ -549,22 +501,25 @@ retry: (p->p_slptime <= 4)) continue; - vm_map_reference(&p->p_vmspace->vm_map); + ++vm->vm_refcnt; + vm_map_reference(&vm->vm_map); /* * do not swapout a process that is waiting for VM * datastructures there is a possible deadlock. */ - if (!lock_try_write(&p->p_vmspace->vm_map.lock)) { - vm_map_deallocate(&p->p_vmspace->vm_map); + if (!lock_try_write(&vm->vm_map.lock)) { + vm_map_deallocate(&vm->vm_map); + vmspace_free(vm); continue; } - vm_map_unlock(&p->p_vmspace->vm_map); + vm_map_unlock(&vm->vm_map); /* * If the process has been asleep for awhile and had * most of its pages taken away already, swap it out. */ swapout(p); - vm_map_deallocate(&p->p_vmspace->vm_map); + vm_map_deallocate(&vm->vm_map); + vmspace_free(vm); didswap++; goto retry; } @@ -612,6 +567,7 @@ swapout(p) panic("swapout: upage already missing???"); m->dirty = VM_PAGE_BITS_ALL; vm_page_unwire(m); + vm_page_deactivate(m); pmap_kremove( (vm_offset_t) p->p_addr + PAGE_SIZE * i); } pmap_remove(pmap, (vm_offset_t) kstack, diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index a820f9d..fbad3f1 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_kern.c,v 1.23 1996/04/24 04:16:44 dyson Exp $ + * $Id: vm_kern.c,v 1.24 1996/05/10 19:28:54 wollman Exp $ */ /* @@ -100,6 +100,7 @@ vm_map_t io_map; vm_map_t clean_map; vm_map_t phys_map; vm_map_t exec_map; +vm_map_t exech_map; vm_map_t u_map; /* @@ -327,22 +328,8 @@ kmem_malloc(map, size, waitflag) vm_map_insert(map, kmem_object, offset, addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); - /* - * If we can wait, just mark the range as wired (will fault pages as - * necessary). - */ - if (waitflag == M_WAITOK) { - vm_map_unlock(map); - (void) vm_map_pageable(map, (vm_offset_t) addr, addr + size, - FALSE); - vm_map_simplify(map, addr); - return (addr); - } - /* - * If we cannot wait then we must allocate all memory up front, - * pulling it off the active queue to prevent pageout. - */ for (i = 0; i < size; i += PAGE_SIZE) { +retry: m = vm_page_alloc(kmem_object, OFF_TO_IDX(offset + i), (waitflag == M_NOWAIT) ? VM_ALLOC_INTERRUPT : VM_ALLOC_SYSTEM); @@ -352,6 +339,10 @@ kmem_malloc(map, size, waitflag) * aren't on any queues. */ if (m == NULL) { + if (waitflag == M_WAITOK) { + VM_WAIT; + goto retry; + } while (i != 0) { i -= PAGE_SIZE; m = vm_page_lookup(kmem_object, @@ -362,7 +353,7 @@ kmem_malloc(map, size, waitflag) vm_map_unlock(map); return (0); } - m->flags &= ~(PG_BUSY|PG_ZERO); + m->flags &= ~PG_ZERO; m->valid = VM_PAGE_BITS_ALL; } @@ -386,7 +377,9 @@ kmem_malloc(map, size, waitflag) for (i = 0; i < size; i += PAGE_SIZE) { m = vm_page_lookup(kmem_object, OFF_TO_IDX(offset + i)); vm_page_wire(m); - pmap_kenter(addr + i, VM_PAGE_TO_PHYS(m)); + PAGE_WAKEUP(m); + pmap_enter(kernel_pmap, addr + i, VM_PAGE_TO_PHYS(m), + VM_PROT_ALL, 1); } vm_map_unlock(map); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 6195309..e0948e4 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.43 1996/04/29 22:04:57 dyson Exp $ + * $Id: vm_map.c,v 1.44 1996/05/03 21:01:49 phk Exp $ */ /* @@ -157,11 +157,15 @@ static int kentry_count; static vm_offset_t mapvm_start, mapvm, mapvmmax; static int mapvmpgcnt; +static struct vm_map_entry *mappool; +static int mappoolcnt; +#define KENTRY_LOW_WATER 128 + static void _vm_map_clip_end __P((vm_map_t, vm_map_entry_t, vm_offset_t)); static void _vm_map_clip_start __P((vm_map_t, vm_map_entry_t, vm_offset_t)); static vm_map_entry_t vm_map_entry_create __P((vm_map_t)); static void vm_map_entry_delete __P((vm_map_t, vm_map_entry_t)); -static void vm_map_entry_dispose __P((vm_map_t, vm_map_entry_t)); +static __inline void vm_map_entry_dispose __P((vm_map_t, vm_map_entry_t)); static void vm_map_entry_unwire __P((vm_map_t, vm_map_entry_t)); static void vm_map_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t)); @@ -214,11 +218,10 @@ vmspace_alloc(min, max, pageable) if (mapvmpgcnt == 0 && mapvm == 0) { int s; - mapvmpgcnt = btoc(cnt.v_page_count * sizeof(struct vm_map_entry)); - s = splhigh(); - mapvm_start = mapvm = kmem_alloc_pageable(kernel_map, mapvmpgcnt * PAGE_SIZE); + mapvmpgcnt = (cnt.v_page_count * sizeof(struct vm_map_entry) + PAGE_SIZE - 1) / PAGE_SIZE; + mapvm_start = mapvm = kmem_alloc_pageable(kernel_map, + mapvmpgcnt * PAGE_SIZE); mapvmmax = mapvm_start + mapvmpgcnt * PAGE_SIZE; - splx(s); if (!mapvm) mapvmpgcnt = 0; } @@ -241,7 +244,6 @@ vmspace_free(vm) panic("vmspace_free: attempt to free already freed vmspace"); if (--vm->vm_refcnt == 0) { - int s, i; /* * Lock the map, to wait out all other references to it. @@ -252,11 +254,17 @@ vmspace_free(vm) (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset, vm->vm_map.max_offset); vm_map_unlock(&vm->vm_map); + while( vm->vm_map.ref_count != 1) tsleep(&vm->vm_map.ref_count, PVM, "vmsfre", 0); --vm->vm_map.ref_count; + vm_object_pmap_remove(vm->vm_upages_obj, + 0, vm->vm_upages_obj->size); + vm_object_deallocate(vm->vm_upages_obj); pmap_release(&vm->vm_pmap); FREE(vm, M_VMMAP); + } else { + wakeup(&vm->vm_map.ref_count); } } @@ -315,44 +323,65 @@ vm_map_init(map, min, max, pageable) } /* + * vm_map_entry_dispose: [ internal use only ] + * + * Inverse of vm_map_entry_create. + */ +static __inline void +vm_map_entry_dispose(map, entry) + vm_map_t map; + vm_map_entry_t entry; +{ + int s; + + if (kentry_count < KENTRY_LOW_WATER) { + s = splvm(); + entry->next = kentry_free; + kentry_free = entry; + ++kentry_count; + splx(s); + } else { + entry->next = mappool; + mappool = entry; + ++mappoolcnt; + } +} + +/* * vm_map_entry_create: [ internal use only ] * * Allocates a VM map entry for insertion. * No entry fields are filled in. This routine is */ -static struct vm_map_entry *mappool; -static int mappoolcnt; - static vm_map_entry_t vm_map_entry_create(map) vm_map_t map; { vm_map_entry_t entry; int i; - -#define KENTRY_LOW_WATER 64 -#define MAPENTRY_LOW_WATER 128 + int s; /* * This is a *very* nasty (and sort of incomplete) hack!!!! */ if (kentry_count < KENTRY_LOW_WATER) { + s = splvm(); if (mapvmpgcnt && mapvm) { vm_page_t m; m = vm_page_alloc(kernel_object, - OFF_TO_IDX(mapvm - vm_map_min(kernel_map)), + OFF_TO_IDX(mapvm - VM_MIN_KERNEL_ADDRESS), (map == kmem_map) ? VM_ALLOC_INTERRUPT : VM_ALLOC_NORMAL); + if (m) { int newentries; newentries = (PAGE_SIZE / sizeof(struct vm_map_entry)); vm_page_wire(m); - m->flags &= ~PG_BUSY; + PAGE_WAKEUP(m); m->valid = VM_PAGE_BITS_ALL; - pmap_enter(vm_map_pmap(kmem_map), mapvm, - VM_PAGE_TO_PHYS(m), VM_PROT_DEFAULT, 1); - m->flags |= PG_WRITEABLE|PG_MAPPED; + pmap_kenter(mapvm, VM_PAGE_TO_PHYS(m)); + m->flags |= PG_WRITEABLE; entry = (vm_map_entry_t) mapvm; mapvm += PAGE_SIZE; @@ -364,66 +393,34 @@ vm_map_entry_create(map) } } } + splx(s); } - if (map == kernel_map || map == kmem_map || map == pager_map) { + if (map == kernel_map || map == kmem_map || map == pager_map) { + s = splvm(); entry = kentry_free; if (entry) { kentry_free = entry->next; --kentry_count; - return entry; - } - entry = mappool; - if (entry) { - mappool = entry->next; - --mappoolcnt; - return entry; + } else { + panic("vm_map_entry_create: out of map entries for kernel"); } + splx(s); } else { entry = mappool; if (entry) { mappool = entry->next; --mappoolcnt; - return entry; + } else { + MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry), + M_VMMAPENT, M_WAITOK); } - MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry), - M_VMMAPENT, M_WAITOK); } - if (entry == NULL) - panic("vm_map_entry_create: out of map entries"); return (entry); } /* - * vm_map_entry_dispose: [ internal use only ] - * - * Inverse of vm_map_entry_create. - */ -static void -vm_map_entry_dispose(map, entry) - vm_map_t map; - vm_map_entry_t entry; -{ - if ((kentry_count < KENTRY_LOW_WATER) || - ((vm_offset_t) entry >= kentry_data && (vm_offset_t) entry < (kentry_data + kentry_data_size)) || - ((vm_offset_t) entry >= mapvm_start && (vm_offset_t) entry < mapvmmax)) { - entry->next = kentry_free; - kentry_free = entry; - ++kentry_count; - return; - } else { - if (mappoolcnt < MAPENTRY_LOW_WATER) { - entry->next = mappool; - mappool = entry; - ++mappoolcnt; - return; - } - FREE(entry, M_VMMAPENT); - } -} - -/* * vm_map_entry_{un,}link: * * Insert/remove entries from maps. @@ -637,9 +634,9 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) if ((prev_entry != &map->header) && (prev_entry->end == start) && + ((object == NULL) || (prev_entry->object.vm_object == object)) && (prev_entry->is_a_map == FALSE) && (prev_entry->is_sub_map == FALSE) && - ((object == NULL) || (prev_entry->object.vm_object == object)) && (prev_entry->inheritance == VM_INHERIT_DEFAULT) && (prev_entry->protection == prot) && (prev_entry->max_protection == max) && @@ -664,13 +661,7 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) prev_entry->end = end; return (KERN_SUCCESS); } - } /* else if ((object == prev_entry->object.vm_object) && - (prev_entry->offset + (prev_entry->end - prev_entry->start) == offset)) { - map->size += (end - prev_entry->end); - prev_entry->end = end; - printf("map optim 1\n"); - return (KERN_SUCCESS); - } */ + } } /* * Create a new entry @@ -711,7 +702,6 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) /* * Update the free space hint */ - if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start)) map->first_free = new_entry; @@ -803,7 +793,7 @@ vm_map_find(map, object, offset, addr, length, find_space, prot, max, cow) start = *addr; if (map == kmem_map) - s = splhigh(); + s = splvm(); vm_map_lock(map); if (find_space) { @@ -866,10 +856,13 @@ vm_map_simplify_entry(map, entry) (prev->wired_count == 0)) { if (map->first_free == prev) map->first_free = entry; + if (map->hint == prev) + map->hint = entry; vm_map_entry_unlink(map, prev); entry->start = prev->start; entry->offset = prev->offset; - vm_object_deallocate(prev->object.vm_object); + if (prev->object.vm_object) + vm_object_deallocate(prev->object.vm_object); vm_map_entry_dispose(map, prev); } } @@ -891,9 +884,12 @@ vm_map_simplify_entry(map, entry) (next->wired_count == 0)) { if (map->first_free == next) map->first_free = entry; + if (map->hint == next) + map->hint = entry; vm_map_entry_unlink(map, next); entry->end = next->end; - vm_object_deallocate(next->object.vm_object); + if (next->object.vm_object) + vm_object_deallocate(next->object.vm_object); vm_map_entry_dispose(map, next); } } @@ -1131,7 +1127,6 @@ vm_map_protect(map, start, end, new_prot, set_max) */ if (current->protection != old_prot) { - #define MASK(entry) ((entry)->copy_on_write ? ~VM_PROT_WRITE : \ VM_PROT_ALL) #define max(a,b) ((a) > (b) ? (a) : (b)) @@ -1585,7 +1580,7 @@ vm_map_clean(map, start, end, syncio, invalidate) * The map in question should be locked. * [This is the reason for this routine's existence.] */ -static void +static __inline void vm_map_entry_unwire(map, entry) vm_map_t map; register vm_map_entry_t entry; @@ -1599,7 +1594,7 @@ vm_map_entry_unwire(map, entry) * * Deallocate the given entry from the target map. */ -static void +static __inline void vm_map_entry_delete(map, entry) register vm_map_t map; register vm_map_entry_t entry; @@ -1658,7 +1653,9 @@ vm_map_delete(map, start, end) * Save the free space hint */ - if (map->first_free->start >= start) + if (entry == &map->header) { + map->first_free = &map->header; + } else if (map->first_free->start >= start) map->first_free = entry->prev; /* @@ -1667,14 +1664,16 @@ vm_map_delete(map, start, end) while ((entry != &map->header) && (entry->start < end)) { vm_map_entry_t next; - register vm_offset_t s, e; - register vm_object_t object; + vm_offset_t s, e; + vm_object_t object; + vm_ooffset_t offset; vm_map_clip_end(map, entry, end); next = entry->next; s = entry->start; e = entry->end; + offset = entry->offset; /* * Unwire before removing addresses from the pmap; otherwise, @@ -1691,15 +1690,16 @@ vm_map_delete(map, start, end) * which are sharing it. */ - if (object == kernel_object || object == kmem_object) - vm_object_page_remove(object, OFF_TO_IDX(entry->offset), - OFF_TO_IDX(entry->offset + (e - s)), FALSE); - else if (!map->is_main_map) + if (object == kernel_object || object == kmem_object) { + vm_object_page_remove(object, OFF_TO_IDX(offset), + OFF_TO_IDX(offset + (e - s)), FALSE); + } else if (!map->is_main_map) { vm_object_pmap_remove(object, - OFF_TO_IDX(entry->offset), - OFF_TO_IDX(entry->offset + (e - s))); - else + OFF_TO_IDX(offset), + OFF_TO_IDX(offset + (e - s))); + } else { pmap_remove(map->pmap, s, e); + } /* * Delete the entry (which may delete the object) only after @@ -1729,7 +1729,7 @@ vm_map_remove(map, start, end) register int result, s = 0; if (map == kmem_map) - s = splhigh(); + s = splvm(); vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); @@ -1806,16 +1806,6 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) if (src_entry->is_sub_map || dst_entry->is_sub_map) return; - if (dst_entry->object.vm_object != NULL) - printf("vm_map_copy_entry: dst_entry object not NULL!\n"); - - /* - * If our destination map was wired down, unwire it now. - */ - - if (dst_entry->wired_count != 0) - vm_map_entry_unwire(dst_map, dst_entry); - if (src_entry->wired_count == 0) { boolean_t src_needs_copy; @@ -1847,35 +1837,28 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) - src_entry->start))); } } + /* * Make a copy of the object. */ - temp_pindex = OFF_TO_IDX(dst_entry->offset); - vm_object_copy(src_entry->object.vm_object, - OFF_TO_IDX(src_entry->offset), - &dst_entry->object.vm_object, - &temp_pindex, - &src_needs_copy); - dst_entry->offset = IDX_TO_OFF(temp_pindex); - /* - * If we didn't get a copy-object now, mark the source map - * entry so that a shadow will be created to hold its changed - * pages. - */ - if (src_needs_copy) + if (src_entry->object.vm_object) { + if ((src_entry->object.vm_object->handle == NULL) && + (src_entry->object.vm_object->type == OBJT_DEFAULT || + src_entry->object.vm_object->type == OBJT_SWAP)) + vm_object_collapse(src_entry->object.vm_object); + ++src_entry->object.vm_object->ref_count; + src_entry->copy_on_write = TRUE; src_entry->needs_copy = TRUE; - /* - * The destination always needs to have a shadow created. - */ - dst_entry->needs_copy = TRUE; - - /* - * Mark the entries copy-on-write, so that write-enabling the - * entry won't make copy-on-write pages writable. - */ - src_entry->copy_on_write = TRUE; - dst_entry->copy_on_write = TRUE; + dst_entry->needs_copy = TRUE; + dst_entry->copy_on_write = TRUE; + dst_entry->object.vm_object = + src_entry->object.vm_object; + dst_entry->offset = src_entry->offset; + } else { + dst_entry->object.vm_object = NULL; + dst_entry->offset = 0; + } pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start, dst_entry->end - dst_entry->start, src_entry->start); @@ -1962,7 +1945,6 @@ vmspace_fork(vm1) /* * Clone the entry and link into the map. */ - new_entry = vm_map_entry_create(new_map); *new_entry = *old_entry; new_entry->wired_count = 0; @@ -2251,11 +2233,13 @@ vm_map_simplify(map, start) vm_map_entry_t prev_entry; vm_map_lock(map); - if ( - (vm_map_lookup_entry(map, start, &this_entry)) && + if ((vm_map_lookup_entry(map, start, &this_entry)) && ((prev_entry = this_entry->prev) != &map->header) && - (prev_entry->end == start) && + (prev_entry->object.vm_object == this_entry->object.vm_object) && + ((prev_entry->offset + (prev_entry->end - prev_entry->start)) + == this_entry->offset) && + (map->is_main_map) && (prev_entry->is_a_map == FALSE) && @@ -2270,18 +2254,15 @@ vm_map_simplify(map, start) (prev_entry->wired_count == this_entry->wired_count) && (prev_entry->copy_on_write == this_entry->copy_on_write) && - (prev_entry->needs_copy == this_entry->needs_copy) && - - (prev_entry->object.vm_object == this_entry->object.vm_object) && - ((prev_entry->offset + (prev_entry->end - prev_entry->start)) - == this_entry->offset) - ) { + (prev_entry->needs_copy == this_entry->needs_copy)) { if (map->first_free == this_entry) map->first_free = prev_entry; - SAVE_HINT(map, prev_entry); + if (map->hint == this_entry) + SAVE_HINT(map, prev_entry); vm_map_entry_unlink(map, this_entry); prev_entry->end = this_entry->end; - vm_object_deallocate(this_entry->object.vm_object); + if (this_entry->object.vm_object) + vm_object_deallocate(this_entry->object.vm_object); vm_map_entry_dispose(map, this_entry); } vm_map_unlock(map); diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index ade41bc..6481309 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 - * $Id: vm_meter.c,v 1.13 1995/12/14 09:55:02 phk Exp $ + * $Id: vm_meter.c,v 1.14 1996/03/11 06:11:40 hsu Exp $ */ #include <sys/param.h> @@ -136,9 +136,9 @@ vmtotal SYSCTL_HANDLER_ARGS /* * Mark all objects as inactive. */ - for (object = vm_object_list.tqh_first; + for (object = TAILQ_FIRST(&vm_object_list); object != NULL; - object = object->object_list.tqe_next) + object = TAILQ_NEXT(object,object_list)) object->flags &= ~OBJ_ACTIVE; /* * Calculate process statistics. @@ -191,9 +191,9 @@ vmtotal SYSCTL_HANDLER_ARGS /* * Calculate object memory usage statistics. */ - for (object = vm_object_list.tqh_first; + for (object = TAILQ_FIRST(&vm_object_list); object != NULL; - object = object->object_list.tqe_next) { + object = TAILQ_NEXT(object, object_list)) { totalp->t_vm += num_pages(object->size); totalp->t_rm += object->resident_page_count; if (object->flags & OBJ_ACTIVE) { diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index ede01dc..16f8ebe 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -38,7 +38,7 @@ * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ * * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 - * $Id: vm_mmap.c,v 1.40 1996/03/16 15:00:05 davidg Exp $ + * $Id: vm_mmap.c,v 1.41 1996/05/03 21:01:51 phk Exp $ */ /* @@ -802,8 +802,7 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff) /* * "Pre-fault" resident pages. */ - if ((map != kernel_map) && - (type == OBJT_VNODE) && (map->pmap != NULL)) { + if ((type == OBJT_VNODE) && (map->pmap != NULL)) { pmap_object_init_pt(map->pmap, *addr, object, (vm_pindex_t) OFF_TO_IDX(foff), size); } diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 6b180ae..187e777 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.67 1996/03/29 06:28:48 davidg Exp $ + * $Id: vm_object.c,v 1.68 1996/04/24 04:16:45 dyson Exp $ */ /* @@ -278,7 +278,7 @@ vm_object_deallocate(object) (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { vm_object_t robject; - robject = object->shadow_head.tqh_first; + robject = TAILQ_FIRST(&object->shadow_head); if ((robject != NULL) && (robject->handle == NULL) && (robject->type == OBJT_DEFAULT || @@ -288,7 +288,7 @@ vm_object_deallocate(object) object->ref_count += 2; do { - s = splhigh(); + s = splvm(); while (robject->paging_in_progress) { robject->flags |= OBJ_PIPWNT; tsleep(robject, PVM, "objde1", 0); @@ -375,7 +375,7 @@ vm_object_terminate(object) /* * wait for the pageout daemon to be done with the object */ - s = splhigh(); + s = splvm(); while (object->paging_in_progress) { object->flags |= OBJ_PIPWNT; tsleep(object, PVM, "objtrm", 0); @@ -402,9 +402,10 @@ vm_object_terminate(object) * Now free the pages. For internal objects, this also removes them * from paging queues. */ - while ((p = object->memq.tqh_first) != NULL) { + while ((p = TAILQ_FIRST(&object->memq)) != NULL) { if (p->flags & PG_BUSY) printf("vm_object_terminate: freeing busy page\n"); + vm_page_protect(p, VM_PROT_NONE); PAGE_WAKEUP(p); vm_page_free(p); cnt.v_pfree++; @@ -478,12 +479,12 @@ vm_object_page_clean(object, start, end, syncio, lockflag) if ((tstart == 0) && (tend == object->size)) { object->flags &= ~(OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY); } - for(p = object->memq.tqh_first; p; p = p->listq.tqe_next) + for(p = TAILQ_FIRST(&object->memq); p; p = TAILQ_NEXT(p, listq)) p->flags |= PG_CLEANCHK; rescan: - for(p = object->memq.tqh_first; p; p = np) { - np = p->listq.tqe_next; + for(p = TAILQ_FIRST(&object->memq); p; p = np) { + np = TAILQ_NEXT(p, listq); pi = p->pindex; if (((p->flags & PG_CLEANCHK) == 0) || @@ -499,7 +500,7 @@ rescan: continue; } - s = splhigh(); + s = splvm(); if ((p->flags & PG_BUSY) || p->busy) { p->flags |= PG_WANTED|PG_REFERENCED; tsleep(p, PVM, "vpcwai", 0); @@ -597,8 +598,8 @@ vm_object_deactivate_pages(object) { register vm_page_t p, next; - for (p = object->memq.tqh_first; p != NULL; p = next) { - next = p->listq.tqe_next; + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { + next = TAILQ_NEXT(p, listq); vm_page_deactivate(p); } } @@ -613,7 +614,7 @@ vm_object_cache_trim() register vm_object_t object; while (vm_object_cached > vm_object_cache_max) { - object = vm_object_cached_list.tqh_first; + object = TAILQ_FIRST(&vm_object_cached_list); vm_object_reference(object); pager_cache(object, FALSE); @@ -641,7 +642,7 @@ vm_object_pmap_copy(object, start, end) if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) return; - for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) { + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { vm_page_protect(p, VM_PROT_READ); } @@ -665,7 +666,7 @@ vm_object_pmap_remove(object, start, end) register vm_page_t p; if (object == NULL) return; - for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) { + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { if (p->pindex >= start && p->pindex < end) vm_page_protect(p, VM_PROT_NONE); } @@ -808,17 +809,16 @@ vm_object_qcollapse(object) backing_object_paging_offset_index = OFF_TO_IDX(backing_object->paging_offset); paging_offset_index = OFF_TO_IDX(object->paging_offset); size = object->size; - p = backing_object->memq.tqh_first; + p = TAILQ_FIRST(&backing_object->memq); while (p) { vm_page_t next; - next = p->listq.tqe_next; + next = TAILQ_NEXT(p, listq); if ((p->flags & (PG_BUSY | PG_FICTITIOUS)) || (p->queue == PQ_CACHE) || !p->valid || p->hold_count || p->wire_count || p->busy) { p = next; continue; } - vm_page_protect(p, VM_PROT_NONE); new_pindex = p->pindex - backing_offset_index; if (p->pindex < backing_offset_index || new_pindex >= size) { @@ -826,6 +826,7 @@ vm_object_qcollapse(object) swap_pager_freespace(backing_object, backing_object_paging_offset_index+p->pindex, 1); + vm_page_protect(p, VM_PROT_NONE); vm_page_free(p); } else { pp = vm_page_lookup(object, new_pindex); @@ -834,6 +835,7 @@ vm_object_qcollapse(object) if (backing_object->type == OBJT_SWAP) swap_pager_freespace(backing_object, backing_object_paging_offset_index + p->pindex, 1); + vm_page_protect(p, VM_PROT_NONE); vm_page_free(p); } else { if (backing_object->type == OBJT_SWAP) @@ -930,7 +932,7 @@ vm_object_collapse(object) * shadow them. */ - while ((p = backing_object->memq.tqh_first) != 0) { + while ((p = TAILQ_FIRST(&backing_object->memq)) != 0) { new_pindex = p->pindex - backing_offset_index; @@ -1071,7 +1073,7 @@ vm_object_collapse(object) * here. */ - for (p = backing_object->memq.tqh_first; p; p = p->listq.tqe_next) { + for (p = TAILQ_FIRST(&backing_object->memq); p; p = TAILQ_NEXT(p, listq)) { new_pindex = p->pindex - backing_offset_index; /* @@ -1160,24 +1162,29 @@ vm_object_page_remove(object, start, end, clean_only) again: size = end - start; if (size > 4 || size >= object->size / 4) { - for (p = object->memq.tqh_first; p != NULL; p = next) { - next = p->listq.tqe_next; + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { + next = TAILQ_NEXT(p, listq); if ((start <= p->pindex) && (p->pindex < end)) { - if (p->wire_count != 0) { vm_page_protect(p, VM_PROT_NONE); p->valid = 0; continue; } - s = splhigh(); + /* + * The busy flags are only cleared at + * interrupt -- minimize the spl transitions + */ if ((p->flags & PG_BUSY) || p->busy) { - p->flags |= PG_WANTED; - tsleep(p, PVM, "vmopar", 0); + s = splvm(); + if ((p->flags & PG_BUSY) || p->busy) { + p->flags |= PG_WANTED; + tsleep(p, PVM, "vmopar", 0); + splx(s); + goto again; + } splx(s); - goto again; } - splx(s); if (clean_only) { vm_page_test_dirty(p); @@ -1199,14 +1206,20 @@ again: size -= 1; continue; } - s = splhigh(); + /* + * The busy flags are only cleared at + * interrupt -- minimize the spl transitions + */ if ((p->flags & PG_BUSY) || p->busy) { - p->flags |= PG_WANTED; - tsleep(p, PVM, "vmopar", 0); + s = splvm(); + if ((p->flags & PG_BUSY) || p->busy) { + p->flags |= PG_WANTED; + tsleep(p, PVM, "vmopar", 0); + splx(s); + goto again; + } splx(s); - goto again; } - splx(s); if (clean_only) { vm_page_test_dirty(p); if (p->valid & p->dirty) { @@ -1391,9 +1404,9 @@ DDB_vm_object_check() * make sure that internal objs are in a map somewhere * and none have zero ref counts. */ - for (object = vm_object_list.tqh_first; + for (object = TAILQ_FIRST(&vm_object_list); object != NULL; - object = object->object_list.tqe_next) { + object = TAILQ_NEXT(object, object_list)) { if (object->handle == NULL && (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { if (object->ref_count == 0) { @@ -1436,14 +1449,14 @@ vm_object_print(iobject, full, dummy3, dummy4) (int) object->paging_offset, (int) object->backing_object, (int) object->backing_object_offset); printf("cache: next=%p, prev=%p\n", - object->cached_list.tqe_next, object->cached_list.tqe_prev); + TAILQ_NEXT(object, cached_list), TAILQ_PREV(object, cached_list)); if (!full) return; indent += 2; count = 0; - for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) { + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { if (count == 0) iprintf("memory:="); else if (count == 6) { diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 6f10cea..7a95941 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $Id: vm_page.c,v 1.49 1996/03/09 06:56:39 dyson Exp $ + * $Id: vm_page.c,v 1.50 1996/03/28 04:53:27 dyson Exp $ */ /* @@ -140,7 +140,6 @@ static u_short vm_page_dev_bsize_chunks[] = { static inline __pure int vm_page_hash __P((vm_object_t object, vm_pindex_t pindex)) __pure2; -static void vm_page_unqueue __P((vm_page_t )); /* * vm_set_page_size: @@ -244,7 +243,7 @@ vm_page_startup(starta, enda, vaddr) vm_page_buckets = (struct pglist *) vaddr; bucket = vm_page_buckets; if (vm_page_bucket_count == 0) { - vm_page_bucket_count = 2; + vm_page_bucket_count = 1; while (vm_page_bucket_count < atop(total)) vm_page_bucket_count <<= 1; } @@ -383,7 +382,7 @@ vm_page_hash(object, pindex) * The object and page must be locked, and must be splhigh. */ -inline void +__inline void vm_page_insert(m, object, pindex) register vm_page_t m; register vm_object_t object; @@ -432,7 +431,7 @@ vm_page_insert(m, object, pindex) * The object and page must be locked, and at splhigh. */ -inline void +__inline void vm_page_remove(m) register vm_page_t m; { @@ -487,14 +486,13 @@ vm_page_lookup(object, pindex) bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; - s = splhigh(); - for (m = bucket->tqh_first; m != NULL; m = m->hashq.tqe_next) { + s = splvm(); + for (m = TAILQ_FIRST(bucket); m != NULL; m = TAILQ_NEXT(m,hashq)) { if ((m->object == object) && (m->pindex == pindex)) { splx(s); return (m); } } - splx(s); return (NULL); } @@ -515,7 +513,7 @@ vm_page_rename(m, new_object, new_pindex) { int s; - s = splhigh(); + s = splvm(); vm_page_remove(m); vm_page_insert(m, new_object, new_pindex); splx(s); @@ -524,7 +522,7 @@ vm_page_rename(m, new_object, new_pindex) /* * vm_page_unqueue must be called at splhigh(); */ -static inline void +__inline void vm_page_unqueue(vm_page_t m) { int queue = m->queue; @@ -575,19 +573,19 @@ vm_page_alloc(object, pindex, page_req) page_req = VM_ALLOC_SYSTEM; }; - s = splhigh(); + s = splvm(); switch (page_req) { case VM_ALLOC_NORMAL: if (cnt.v_free_count >= cnt.v_free_reserved) { - m = vm_page_queue_free.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_free); if (m == NULL) { --vm_page_zero_count; - m = vm_page_queue_zero.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_zero); } } else { - m = vm_page_queue_cache.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_cache); if (m == NULL) { splx(s); pagedaemon_wakeup(); @@ -598,14 +596,14 @@ vm_page_alloc(object, pindex, page_req) case VM_ALLOC_ZERO: if (cnt.v_free_count >= cnt.v_free_reserved) { - m = vm_page_queue_zero.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_zero); if (m) { --vm_page_zero_count; } else { - m = vm_page_queue_free.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_free); } } else { - m = vm_page_queue_cache.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_cache); if (m == NULL) { splx(s); pagedaemon_wakeup(); @@ -618,13 +616,13 @@ vm_page_alloc(object, pindex, page_req) if ((cnt.v_free_count >= cnt.v_free_reserved) || ((cnt.v_cache_count == 0) && (cnt.v_free_count >= cnt.v_interrupt_free_min))) { - m = vm_page_queue_free.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_free); if (m == NULL) { --vm_page_zero_count; - m = vm_page_queue_zero.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_zero); } } else { - m = vm_page_queue_cache.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_cache); if (m == NULL) { splx(s); pagedaemon_wakeup(); @@ -635,10 +633,10 @@ vm_page_alloc(object, pindex, page_req) case VM_ALLOC_INTERRUPT: if (cnt.v_free_count > 0) { - m = vm_page_queue_free.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_free); if (m == NULL) { --vm_page_zero_count; - m = vm_page_queue_zero.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_zero); } } else { splx(s); @@ -663,8 +661,8 @@ vm_page_alloc(object, pindex, page_req) m->flags = PG_BUSY; } m->wire_count = 0; - m->hold_count = 0; m->act_count = 0; + m->hold_count = 0; m->busy = 0; m->valid = 0; m->dirty = 0; @@ -688,114 +686,35 @@ vm_page_alloc(object, pindex, page_req) } /* - * This interface is for merging with malloc() someday. - * Even if we never implement compaction so that contiguous allocation - * works after initialization time, malloc()'s data structures are good - * for statistics and for allocations of less than a page. + * vm_page_activate: + * + * Put the specified page on the active list (if appropriate). + * + * The page queues must be locked. */ -void * -contigmalloc(size, type, flags, low, high, alignment, boundary) - unsigned long size; /* should be size_t here and for malloc() */ - int type; - int flags; - unsigned long low; - unsigned long high; - unsigned long alignment; - unsigned long boundary; +void +vm_page_activate(m) + register vm_page_t m; { - int i, s, start; - vm_offset_t addr, phys, tmp_addr; - vm_page_t pga = vm_page_array; - - size = round_page(size); - if (size == 0) - panic("vm_page_alloc_contig: size must not be 0"); - if ((alignment & (alignment - 1)) != 0) - panic("vm_page_alloc_contig: alignment must be a power of 2"); - if ((boundary & (boundary - 1)) != 0) - panic("vm_page_alloc_contig: boundary must be a power of 2"); - - start = 0; - s = splhigh(); -again: - /* - * Find first page in array that is free, within range, aligned, and - * such that the boundary won't be crossed. - */ - for (i = start; i < cnt.v_page_count; i++) { - phys = VM_PAGE_TO_PHYS(&pga[i]); - if ((pga[i].queue == PQ_FREE) && - (phys >= low) && (phys < high) && - ((phys & (alignment - 1)) == 0) && - (((phys ^ (phys + size - 1)) & ~(boundary - 1)) == 0)) - break; - } - - /* - * If the above failed or we will exceed the upper bound, fail. - */ - if ((i == cnt.v_page_count) || - ((VM_PAGE_TO_PHYS(&pga[i]) + size) > high)) { - splx(s); - return (NULL); - } - start = i; + int s; - /* - * Check successive pages for contiguous and free. - */ - for (i = start + 1; i < (start + size / PAGE_SIZE); i++) { - if ((VM_PAGE_TO_PHYS(&pga[i]) != - (VM_PAGE_TO_PHYS(&pga[i - 1]) + PAGE_SIZE)) || - (pga[i].queue != PQ_FREE)) { - start++; - goto again; - } - } + s = splvm(); + if (m->queue == PQ_ACTIVE) + panic("vm_page_activate: already active"); - /* - * We've found a contiguous chunk that meets are requirements. - * Allocate kernel VM, unfree and assign the physical pages to it and - * return kernel VM pointer. - */ - tmp_addr = addr = kmem_alloc_pageable(kernel_map, size); - if (addr == 0) { - splx(s); - return (NULL); - } + if (m->queue == PQ_CACHE) + cnt.v_reactivated++; - for (i = start; i < (start + size / PAGE_SIZE); i++) { - vm_page_t m = &pga[i]; + vm_page_unqueue(m); - TAILQ_REMOVE(&vm_page_queue_free, m, pageq); - cnt.v_free_count--; - m->valid = VM_PAGE_BITS_ALL; - m->flags = 0; - m->dirty = 0; - m->wire_count = 0; - m->act_count = 0; - m->busy = 0; - m->queue = PQ_NONE; - vm_page_insert(m, kernel_object, - OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS)); - vm_page_wire(m); - pmap_kenter(tmp_addr, VM_PAGE_TO_PHYS(m)); - tmp_addr += PAGE_SIZE; + if (m->wire_count == 0) { + if (m->act_count < 5) + m->act_count = 5; + TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); + m->queue = PQ_ACTIVE; + cnt.v_active_count++; } - splx(s); - return ((void *)addr); -} - -vm_offset_t -vm_page_alloc_contig(size, low, high, alignment) - vm_offset_t size; - vm_offset_t low; - vm_offset_t high; - vm_offset_t alignment; -{ - return ((vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, low, high, - alignment, 0ul)); } /* @@ -813,7 +732,7 @@ vm_page_free(m) int s; int flags = m->flags; - s = splhigh(); + s = splvm(); if (m->busy || (flags & PG_BUSY) || (m->queue == PQ_FREE)) { printf("vm_page_free: pindex(%ld), busy(%d), PG_BUSY(%d)\n", m->pindex, m->busy, (flags & PG_BUSY) ? 1 : 0); @@ -824,7 +743,8 @@ vm_page_free(m) } if (m->hold_count) { - panic("freeing held page, count=%d", m->hold_count); + panic("freeing held page, count=%d, pindex=%d(0x%x)", + m->hold_count, m->pindex, m->pindex); } vm_page_remove(m); @@ -840,7 +760,19 @@ vm_page_free(m) m->wire_count = 0; } m->queue = PQ_FREE; - TAILQ_INSERT_TAIL(&vm_page_queue_free, m, pageq); + + /* + * If the pageout process is grabbing the page, it is likely + * that the page is NOT in the cache. It is more likely that + * the page will be partially in the cache if it is being + * explicitly freed. + */ + if (curproc == pageproc) { + TAILQ_INSERT_TAIL(&vm_page_queue_free, m, pageq); + } else { + TAILQ_INSERT_HEAD(&vm_page_queue_free, m, pageq); + } + splx(s); /* * if pageout daemon needs pages, then tell it that there are @@ -859,7 +791,6 @@ vm_page_free(m) */ if ((cnt.v_free_count + cnt.v_cache_count) == cnt.v_free_min) { wakeup(&cnt.v_free_count); - wakeup(&proc0); } } else { splx(s); @@ -884,7 +815,7 @@ vm_page_wire(m) int s; if (m->wire_count == 0) { - s = splhigh(); + s = splvm(); vm_page_unqueue(m); splx(s); cnt.v_wire_count++; @@ -907,7 +838,7 @@ vm_page_unwire(m) { int s; - s = splhigh(); + s = splvm(); if (m->wire_count > 0) m->wire_count--; @@ -916,47 +847,14 @@ vm_page_unwire(m) cnt.v_wire_count--; TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); m->queue = PQ_ACTIVE; - if( m->act_count < ACT_MAX) - m->act_count += 1; - cnt.v_active_count++; - } - splx(s); -} - -/* - * vm_page_activate: - * - * Put the specified page on the active list (if appropriate). - * - * The page queues must be locked. - */ -void -vm_page_activate(m) - register vm_page_t m; -{ - int s; - - s = splhigh(); - if (m->queue == PQ_ACTIVE) - panic("vm_page_activate: already active"); - - if (m->queue == PQ_CACHE) - cnt.v_reactivated++; - - vm_page_unqueue(m); - - if (m->wire_count == 0) { - TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); - m->queue = PQ_ACTIVE; if (m->act_count < 5) m->act_count = 5; - else if( m->act_count < ACT_MAX) - m->act_count += 1; cnt.v_active_count++; } splx(s); } + /* * vm_page_deactivate: * @@ -982,7 +880,7 @@ vm_page_deactivate(m) if (m->queue == PQ_INACTIVE) return; - spl = splhigh(); + spl = splvm(); if (m->wire_count == 0 && m->hold_count == 0) { if (m->queue == PQ_CACHE) cnt.v_reactivated++; @@ -990,7 +888,6 @@ vm_page_deactivate(m) TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); m->queue = PQ_INACTIVE; cnt.v_inactive_count++; - m->act_count = 0; } splx(spl); } @@ -1014,7 +911,7 @@ vm_page_cache(m) return; vm_page_protect(m, VM_PROT_NONE); - s = splhigh(); + s = splvm(); vm_page_unqueue(m); TAILQ_INSERT_TAIL(&vm_page_queue_cache, m, pageq); m->queue = PQ_CACHE; @@ -1030,35 +927,6 @@ vm_page_cache(m) splx(s); } -/* - * vm_page_zero_fill: - * - * Zero-fill the specified page. - * Written as a standard pagein routine, to - * be used by the zero-fill object. - */ -boolean_t -vm_page_zero_fill(m) - vm_page_t m; -{ - pmap_zero_page(VM_PAGE_TO_PHYS(m)); - return (TRUE); -} - -/* - * vm_page_copy: - * - * Copy one page to another - */ -void -vm_page_copy(src_m, dest_m) - vm_page_t src_m; - vm_page_t dest_m; -{ - pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m)); - dest_m->valid = VM_PAGE_BITS_ALL; -} - /* * mapping function for valid bits or for dirty bits in @@ -1126,8 +994,6 @@ vm_page_is_valid(m, base, size) return 0; } - - void vm_page_test_dirty(m) vm_page_t m; @@ -1138,6 +1004,115 @@ vm_page_test_dirty(m) } } +/* + * This interface is for merging with malloc() someday. + * Even if we never implement compaction so that contiguous allocation + * works after initialization time, malloc()'s data structures are good + * for statistics and for allocations of less than a page. + */ +void * +contigmalloc(size, type, flags, low, high, alignment, boundary) + unsigned long size; /* should be size_t here and for malloc() */ + int type; + int flags; + unsigned long low; + unsigned long high; + unsigned long alignment; + unsigned long boundary; +{ + int i, s, start; + vm_offset_t addr, phys, tmp_addr; + vm_page_t pga = vm_page_array; + + size = round_page(size); + if (size == 0) + panic("vm_page_alloc_contig: size must not be 0"); + if ((alignment & (alignment - 1)) != 0) + panic("vm_page_alloc_contig: alignment must be a power of 2"); + if ((boundary & (boundary - 1)) != 0) + panic("vm_page_alloc_contig: boundary must be a power of 2"); + + start = 0; + s = splvm(); +again: + /* + * Find first page in array that is free, within range, aligned, and + * such that the boundary won't be crossed. + */ + for (i = start; i < cnt.v_page_count; i++) { + phys = VM_PAGE_TO_PHYS(&pga[i]); + if ((pga[i].queue == PQ_FREE) && + (phys >= low) && (phys < high) && + ((phys & (alignment - 1)) == 0) && + (((phys ^ (phys + size - 1)) & ~(boundary - 1)) == 0)) + break; + } + + /* + * If the above failed or we will exceed the upper bound, fail. + */ + if ((i == cnt.v_page_count) || + ((VM_PAGE_TO_PHYS(&pga[i]) + size) > high)) { + splx(s); + return (NULL); + } + start = i; + + /* + * Check successive pages for contiguous and free. + */ + for (i = start + 1; i < (start + size / PAGE_SIZE); i++) { + if ((VM_PAGE_TO_PHYS(&pga[i]) != + (VM_PAGE_TO_PHYS(&pga[i - 1]) + PAGE_SIZE)) || + (pga[i].queue != PQ_FREE)) { + start++; + goto again; + } + } + + /* + * We've found a contiguous chunk that meets are requirements. + * Allocate kernel VM, unfree and assign the physical pages to it and + * return kernel VM pointer. + */ + tmp_addr = addr = kmem_alloc_pageable(kernel_map, size); + if (addr == 0) { + splx(s); + return (NULL); + } + + for (i = start; i < (start + size / PAGE_SIZE); i++) { + vm_page_t m = &pga[i]; + + TAILQ_REMOVE(&vm_page_queue_free, m, pageq); + cnt.v_free_count--; + m->valid = VM_PAGE_BITS_ALL; + m->flags = 0; + m->dirty = 0; + m->wire_count = 0; + m->busy = 0; + m->queue = PQ_NONE; + vm_page_insert(m, kernel_object, + OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS)); + vm_page_wire(m); + pmap_kenter(tmp_addr, VM_PAGE_TO_PHYS(m)); + tmp_addr += PAGE_SIZE; + } + + splx(s); + return ((void *)addr); +} + +vm_offset_t +vm_page_alloc_contig(size, low, high, alignment) + vm_offset_t size; + vm_offset_t low; + vm_offset_t high; + vm_offset_t alignment; +{ + return ((vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, low, high, + alignment, 0ul)); +} #ifdef DDB void DDB_print_page_info(void) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index e10c106..950ebe1 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -65,7 +65,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.c,v 1.69 1996/03/28 04:53:28 dyson Exp $ + * $Id: vm_pageout.c,v 1.70 1996/04/11 21:05:25 bde Exp $ */ /* @@ -138,8 +138,6 @@ extern int nswiodone; extern int vm_swap_size; extern int vfs_update_wakeup; -#define MAXSCAN 1024 /* maximum number of pages to scan in queues */ - #define MAXLAUNDER (cnt.v_page_count > 1800 ? 32 : 16) #define VM_PAGEOUT_PAGE_COUNT 16 @@ -415,9 +413,9 @@ vm_pageout_object_deactivate_pages(map, object, count, map_remove_only) * scan the objects entire memory queue */ rcount = object->resident_page_count; - p = object->memq.tqh_first; + p = TAILQ_FIRST(&object->memq); while (p && (rcount-- > 0)) { - next = p->listq.tqe_next; + next = TAILQ_NEXT(p, listq); cnt.v_pdpages++; if (p->wire_count != 0 || p->hold_count != 0 || @@ -434,26 +432,9 @@ vm_pageout_object_deactivate_pages(map, object, count, map_remove_only) if (p->queue == PQ_ACTIVE) { if (!pmap_is_referenced(VM_PAGE_TO_PHYS(p)) && (p->flags & PG_REFERENCED) == 0) { - p->act_count -= min(p->act_count, ACT_DECLINE); - /* - * if the page act_count is zero -- then we - * deactivate - */ - if (!p->act_count) { - if (!map_remove_only) - vm_page_deactivate(p); - vm_page_protect(p, VM_PROT_NONE); - /* - * else if on the next go-around we - * will deactivate the page we need to - * place the page on the end of the - * queue to age the other pages in - * memory. - */ - } else { - TAILQ_REMOVE(&vm_page_queue_active, p, pageq); - TAILQ_INSERT_TAIL(&vm_page_queue_active, p, pageq); - } + vm_page_protect(p, VM_PROT_NONE); + if (!map_remove_only) + vm_page_deactivate(p); /* * see if we are done yet */ @@ -471,8 +452,6 @@ vm_pageout_object_deactivate_pages(map, object, count, map_remove_only) */ pmap_clear_reference(VM_PAGE_TO_PHYS(p)); p->flags &= ~PG_REFERENCED; - if (p->act_count < ACT_MAX) - p->act_count += ACT_ADVANCE; TAILQ_REMOVE(&vm_page_queue_active, p, pageq); TAILQ_INSERT_TAIL(&vm_page_queue_active, p, pageq); @@ -544,9 +523,12 @@ vm_pageout_scan() vm_object_t object; int force_wakeup = 0; int vnodes_skipped = 0; + int usagefloor; + int i; pages_freed = 0; + /* * Start scanning the inactive queue for pages we can free. We keep * scanning until we have enough free pages or we have scanned through @@ -559,13 +541,14 @@ vm_pageout_scan() rescan1: maxscan = cnt.v_inactive_count; - m = vm_page_queue_inactive.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_inactive); while ((m != NULL) && (maxscan-- > 0) && - ((cnt.v_cache_count + cnt.v_free_count) < (cnt.v_cache_min + cnt.v_free_target))) { + ((cnt.v_cache_count + cnt.v_free_count) < + (cnt.v_cache_min + cnt.v_free_target))) { vm_page_t next; cnt.v_pdpages++; - next = m->pageq.tqe_next; + next = TAILQ_NEXT(m, pageq); #if defined(VM_DIAGNOSE) if (m->queue != PQ_INACTIVE) { @@ -575,7 +558,8 @@ rescan1: #endif /* - * dont mess with busy pages + * Dont mess with busy pages, keep in the front of the + * queue, most likely are being paged out. */ if (m->busy || (m->flags & PG_BUSY)) { m = next; @@ -600,8 +584,6 @@ rescan1: m->flags &= ~PG_REFERENCED; pmap_clear_reference(VM_PAGE_TO_PHYS(m)); vm_page_activate(m); - if (m->act_count < ACT_MAX) - m->act_count += ACT_ADVANCE; m = next; continue; } @@ -681,14 +663,11 @@ rescan1: page_shortage = 1; } } - maxscan = MAXSCAN; - pcount = cnt.v_active_count; - m = vm_page_queue_active.tqh_first; - while ((m != NULL) && (maxscan > 0) && - (pcount-- > 0) && (page_shortage > 0)) { - cnt.v_pdpages++; - next = m->pageq.tqe_next; + pcount = cnt.v_active_count; + m = TAILQ_FIRST(&vm_page_queue_active); + while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) { + next = TAILQ_NEXT(m, pageq); /* * Don't deactivate pages that are busy. @@ -701,54 +680,47 @@ rescan1: m = next; continue; } - if (m->object->ref_count && - ((m->flags & PG_REFERENCED) || - pmap_is_referenced(VM_PAGE_TO_PHYS(m))) ) { + + /* + * The count for pagedaemon pages is done after checking the + * page for eligbility... + */ + cnt.v_pdpages++; + if ((m->flags & PG_REFERENCED) == 0) { + if (pmap_is_referenced(VM_PAGE_TO_PHYS(m))) { + pmap_clear_reference(VM_PAGE_TO_PHYS(m)); + m->flags |= PG_REFERENCED; + } + } else { pmap_clear_reference(VM_PAGE_TO_PHYS(m)); + } + if ( (m->object->ref_count != 0) && + (m->flags & PG_REFERENCED) ) { m->flags &= ~PG_REFERENCED; - if (m->act_count < ACT_MAX) { - m->act_count += ACT_ADVANCE; - } TAILQ_REMOVE(&vm_page_queue_active, m, pageq); TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); } else { m->flags &= ~PG_REFERENCED; - pmap_clear_reference(VM_PAGE_TO_PHYS(m)); - m->act_count -= min(m->act_count, ACT_DECLINE); - - /* - * if the page act_count is zero -- then we deactivate - */ - if (!m->act_count && (page_shortage > 0)) { - if (m->object->ref_count == 0) { - --page_shortage; - vm_page_test_dirty(m); - if (m->dirty == 0) { - m->act_count = 0; - vm_page_cache(m); - } else { - vm_page_deactivate(m); - } + if (page_shortage > 0) { + --page_shortage; + vm_page_test_dirty(m); + if (m->dirty == 0) { + vm_page_cache(m); } else { vm_page_protect(m, VM_PROT_NONE); vm_page_deactivate(m); - --page_shortage; } - } else if (m->act_count) { - TAILQ_REMOVE(&vm_page_queue_active, m, pageq); - TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); } } - maxscan--; m = next; } - + /* * We try to maintain some *really* free pages, this allows interrupt * code to be guaranteed space. */ while (cnt.v_free_count < cnt.v_free_reserved) { - m = vm_page_queue_cache.tqh_first; + m = TAILQ_FIRST(&vm_page_queue_cache); if (!m) break; vm_page_free(m); @@ -770,23 +742,13 @@ rescan1: } } #ifndef NO_SWAPPING - /* - * now swap processes out if we are in low memory conditions - */ - if (!swap_pager_full && vm_swap_size && - vm_pageout_req_swapout == 0) { - vm_pageout_req_swapout = 1; + if (cnt.v_free_count + cnt.v_cache_count < cnt.v_free_target) { vm_req_vmdaemon(); + vm_pageout_req_swapout = 1; } #endif } -#ifndef NO_SWAPPING - if ((cnt.v_inactive_count + cnt.v_free_count + cnt.v_cache_count) < - (cnt.v_inactive_target + cnt.v_free_min)) { - vm_req_vmdaemon(); - } -#endif /* * make sure that we have swap space -- if we are low on memory and @@ -883,22 +845,23 @@ vm_pageout() * The pageout daemon is never done, so loop forever. */ while (TRUE) { - int s = splhigh(); - + int s = splvm(); if (!vm_pages_needed || ((cnt.v_free_count >= cnt.v_free_reserved) && (cnt.v_free_count + cnt.v_cache_count >= cnt.v_free_min))) { vm_pages_needed = 0; tsleep(&vm_pages_needed, PVM, "psleep", 0); + } else if (!vm_pages_needed) { + tsleep(&vm_pages_needed, PVM, "psleep", hz/3); } + if (vm_pages_needed) + cnt.v_pdwakeups++; vm_pages_needed = 0; splx(s); - cnt.v_pdwakeups++; vm_pager_sync(); vm_pageout_scan(); vm_pager_sync(); wakeup(&cnt.v_free_count); - wakeup(kmem_map); } } @@ -908,7 +871,7 @@ vm_req_vmdaemon() { static int lastrun = 0; - if ((ticks > (lastrun + hz / 10)) || (ticks < lastrun)) { + if ((ticks > (lastrun + hz)) || (ticks < lastrun)) { wakeup(&vm_daemon_needed); lastrun = ticks; } @@ -978,7 +941,7 @@ vm_daemon() * we remove cached objects that have no RSS... */ restart: - object = vm_object_cached_list.tqh_first; + object = TAILQ_FIRST(&vm_object_cached_list); while (object) { /* * if there are no resident pages -- get rid of the object @@ -988,7 +951,7 @@ restart: pager_cache(object, FALSE); goto restart; } - object = object->cached_list.tqe_next; + object = TAILQ_NEXT(object, cached_list); } } } diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index 63ebdd9..c7c9964 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pager.c,v 1.21 1995/12/14 09:55:11 phk Exp $ + * $Id: vm_pager.c,v 1.22 1996/05/03 21:01:53 phk Exp $ */ /* @@ -249,7 +249,7 @@ vm_pager_object_lookup(pg_list, handle) { register vm_object_t object; - for (object = pg_list->tqh_first; object != NULL; object = object->pager_object_list.tqe_next) + for (object = TAILQ_FIRST(pg_list); object != NULL; object = TAILQ_NEXT(object,pager_object_list)) if (object->handle == handle) return (object); return (NULL); @@ -288,7 +288,7 @@ getpbuf() s = splbio(); /* get a bp from the swap buffer header pool */ - while ((bp = bswlist.tqh_first) == NULL) { + while ((bp = TAILQ_FIRST(&bswlist)) == NULL) { bswneeded = 1; tsleep(&bswneeded, PVM, "wswbuf", 0); } @@ -313,7 +313,7 @@ trypbuf() struct buf *bp; s = splbio(); - if ((bp = bswlist.tqh_first) == NULL) { + if ((bp = TAILQ_FIRST(&bswlist)) == NULL) { splx(s); return NULL; } |