summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-06-12 20:01:48 +0000
committeralc <alc@FreeBSD.org>2004-06-12 20:01:48 +0000
commitf6af690bdeb2e55a1bdabd5af91a8a601955e892 (patch)
tree2932c2aa045737086a3494b92d63233e95fbc8c1 /sys
parenta1214ecb7b3a5536b459a68adb96489226a904ad (diff)
downloadFreeBSD-src-f6af690bdeb2e55a1bdabd5af91a8a601955e892.zip
FreeBSD-src-f6af690bdeb2e55a1bdabd5af91a8a601955e892.tar.gz
In a multiprocessor, the PG_W bit in the pte must be changed atomically.
Otherwise, the setting of the PG_M bit by one processor could be lost if another processor is simultaneously changing the PG_W bit. Reviewed by: tegge@
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/pmap.c4
-rw-r--r--sys/i386/i386/pmap.c3
2 files changed, 4 insertions, 3 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index d332045..6526987 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -2200,10 +2200,10 @@ pmap_change_wiring(pmap, va, wired)
pte = pmap_pte(pmap, va);
if (wired && (*pte & PG_W) == 0) {
pmap->pm_stats.wired_count++;
- *pte |= PG_W;
+ atomic_set_long(pte, PG_W);
} else if (!wired && (*pte & PG_W) != 0) {
pmap->pm_stats.wired_count--;
- *pte &= ~PG_W;
+ atomic_clear_long(pte, PG_W);
}
}
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 375cfad..32f3b07 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -178,7 +178,8 @@ __FBSDID("$FreeBSD$");
#define pmap_pte_u(pte) ((*(int *)pte & PG_A) != 0)
#define pmap_pte_v(pte) ((*(int *)pte & PG_V) != 0)
-#define pmap_pte_set_w(pte, v) ((v)?(*(int *)pte |= PG_W):(*(int *)pte &= ~PG_W))
+#define pmap_pte_set_w(pte, v) ((v) ? atomic_set_int((u_int *)(pte), PG_W) : \
+ atomic_clear_int((u_int *)(pte), PG_W))
#define pmap_pte_set_prot(pte, v) ((*(int *)pte &= ~PG_PROT), (*(int *)pte |= (v)))
struct pmap kernel_pmap_store;
OpenPOWER on IntegriCloud