diff options
author | Alan Cox <alc@FreeBSD.org> | 2010-05-29 17:10:45 +0000 |
---|---|---|
committer | Alan Cox <alc@FreeBSD.org> | 2010-05-29 17:10:45 +0000 |
commit | 8f0d5d3b9fcf09e3527d319ae4772c702667885f (patch) | |
tree | 09abd6706e74dde3b422058d85e5421c74c98c91 /sys/vm/vm_page.h | |
parent | bf59e055dbc6b314377a6673a0ae66658d2e7a43 (diff) | |
download | src-8f0d5d3b9fcf09e3527d319ae4772c702667885f.tar.gz src-8f0d5d3b9fcf09e3527d319ae4772c702667885f.zip |
When I pushed down the page queues lock into pmap_is_modified(), I created
an ordering dependence: A pmap operation that clears PG_WRITEABLE and calls
vm_page_dirty() must perform the call first. Otherwise, pmap_is_modified()
could return FALSE without acquiring the page queues lock because the page
is not (currently) writeable, and the caller to pmap_is_modified() might
believe that the page's dirty field is clear because it has not seen the
effect of the vm_page_dirty() call.
When I pushed down the page queues lock into pmap_is_modified(), I
overlooked one place where this ordering dependence is violated:
pmap_enter(). In a rare situation pmap_enter() can be called to replace a
dirty mapping to one page with a mapping to another page. (I say rare
because replacements generally occur as a result of a copy-on-write fault,
and so the old page is not dirty.) This change delays clearing PG_WRITEABLE
until after vm_page_dirty() has been called.
Fixing the ordering dependency also makes it easy to introduce a small
optimization: When pmap_enter() used to replace a mapping to one page with a
mapping to another page, it freed the pv entry for the first mapping and
later called the pv entry allocator for the new mapping. Now, pmap_enter()
attempts to recycle the old pv entry, saving two calls to the pv entry
allocator.
There is no point in setting PG_WRITEABLE on unmanaged pages, so don't.
Update a comment to reflect this.
Tidy up the variable declarations at the start of pmap_enter().
Notes
Notes:
svn path=/head/; revision=208645
Diffstat (limited to 'sys/vm/vm_page.h')
-rw-r--r-- | sys/vm/vm_page.h | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index fb1cfda60a79..e8f68d2792cb 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -219,8 +219,8 @@ extern struct vpglocks pa_lock[]; * pte mappings, nor can they be removed from their objects via * the object, and such pages are also not on any PQ queue. * - * PG_WRITEABLE is set exclusively by pmap_enter(). When it does so, the page - * must be VPO_BUSY. + * PG_WRITEABLE is set exclusively on managed pages by pmap_enter(). When it + * does so, the page must be VPO_BUSY. */ #define PG_CACHED 0x0001 /* page is cached */ #define PG_FREE 0x0002 /* page is free */ |