diff options
| author | Alan Cox <alc@FreeBSD.org> | 2004-09-08 18:58:29 +0000 |
|---|---|---|
| committer | Alan Cox <alc@FreeBSD.org> | 2004-09-08 18:58:29 +0000 |
| commit | e232eb828876c2c48e4bdcb4993e7c0ef58b3478 (patch) | |
| tree | 0a164504fbe725b65f661f7a630ed6cd12fc36ff /sys/amd64 | |
| parent | 51eb0765c6f221289cb1837950e7e49b3aa63c4d (diff) | |
Notes
Diffstat (limited to 'sys/amd64')
| -rw-r--r-- | sys/amd64/amd64/pmap.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index abc8447dbd93..72eda83859fe 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -203,7 +203,7 @@ static caddr_t crashdumpmap; static PMAP_INLINE void free_pv_entry(pv_entry_t pv); static pv_entry_t get_pv_entry(void); -static void pmap_clear_ptes(vm_page_t m, int bit); +static void pmap_clear_ptes(vm_page_t m, long bit); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, pd_entry_t ptepde); @@ -2591,7 +2591,7 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr) * Clear the given bit in each of the given page's ptes. */ static __inline void -pmap_clear_ptes(vm_page_t m, int bit) +pmap_clear_ptes(vm_page_t m, long bit) { register pv_entry_t pv; pt_entry_t pbits, *pte; @@ -2623,15 +2623,18 @@ pmap_clear_ptes(vm_page_t m, int bit) PMAP_LOCK(pv->pv_pmap); pte = pmap_pte(pv->pv_pmap, pv->pv_va); +retry: pbits = *pte; if (pbits & bit) { if (bit == PG_RW) { + if (!atomic_cmpset_long(pte, pbits, + pbits & ~(PG_RW | PG_M))) + goto retry; if (pbits & PG_M) { vm_page_dirty(m); } - pte_store(pte, pbits & ~(PG_M|PG_RW)); } else { - pte_store(pte, pbits & ~bit); + atomic_clear_long(pte, bit); } pmap_invalidate_page(pv->pv_pmap, pv->pv_va); } |
