diff options
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/pmap.h | 2 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 21 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 9 |
3 files changed, 21 insertions, 11 deletions
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h index c0f80a7..911298f 100644 --- a/sys/vm/pmap.h +++ b/sys/vm/pmap.h @@ -98,6 +98,8 @@ struct thread; extern vm_offset_t kernel_vm_end; void pmap_activate(struct thread *td); +void pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, + int advice); void pmap_align_superpage(vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t); void pmap_change_wiring(pmap_t, vm_offset_t, boolean_t); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 71c44ad..1be62af 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2125,7 +2125,7 @@ vm_map_madvise( (current != &map->header) && (current->start < end); current = current->next ) { - vm_offset_t useStart; + vm_offset_t useEnd, useStart; if (current->eflags & MAP_ENTRY_IS_SUB_MAP) continue; @@ -2133,17 +2133,34 @@ vm_map_madvise( pstart = OFF_TO_IDX(current->offset); pend = pstart + atop(current->end - current->start); useStart = current->start; + useEnd = current->end; if (current->start < start) { pstart += atop(start - current->start); useStart = start; } - if (current->end > end) + if (current->end > end) { pend -= atop(current->end - end); + useEnd = end; + } if (pstart >= pend) continue; + /* + * Perform the pmap_advise() before clearing + * PGA_REFERENCED in vm_page_advise(). Otherwise, a + * concurrent pmap operation, such as pmap_remove(), + * could clear a reference in the pmap and set + * PGA_REFERENCED on the page before the pmap_advise() + * had completed. Consequently, the page would appear + * referenced based upon an old reference that + * occurred before this pmap_advise() ran. + */ + if (behav == MADV_DONTNEED || behav == MADV_FREE) + pmap_advise(map->pmap, useStart, useEnd, + behav); + vm_object_madvise(current->object.vm_object, pstart, pend, behav); if (behav == MADV_WILLNEED) { diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 7d8ecfa..7b4b57c 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -2634,7 +2634,6 @@ vm_page_advise(vm_page_t m, int advice) * But we do make the page is freeable as we can without * actually taking the step of unmapping it. */ - pmap_clear_modify(m); m->dirty = 0; m->act_count = 0; } else if (advice != MADV_DONTNEED) @@ -2654,15 +2653,7 @@ vm_page_advise(vm_page_t m, int advice) /* * Clear any references to the page. Otherwise, the page daemon will * immediately reactivate the page. - * - * Perform the pmap_clear_reference() first. Otherwise, a concurrent - * pmap operation, such as pmap_remove(), could clear a reference in - * the pmap and set PGA_REFERENCED on the page before the - * pmap_clear_reference() had completed. Consequently, the page would - * appear referenced based upon an old reference that occurred before - * this function ran. */ - pmap_clear_reference(m); vm_page_aflag_clear(m, PGA_REFERENCED); if (advice != MADV_FREE && m->dirty == 0 && pmap_is_modified(m)) |