summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>1999-03-02 22:55:02 +0000
committeralc <alc@FreeBSD.org>1999-03-02 22:55:02 +0000
commit9e3d479b9d7509856e6dc91e1c69dc2e9165b908 (patch)
tree96191ebe82bd42f9a978ff29e4a0aaa24e86575c /sys/vm
parent4e5c23f7a19f274c7684cd2771a113f2f2cc6689 (diff)
downloadFreeBSD-src-9e3d479b9d7509856e6dc91e1c69dc2e9165b908.zip
FreeBSD-src-9e3d479b9d7509856e6dc91e1c69dc2e9165b908.tar.gz
To avoid a conflict for the vm_map's lock with vm_fault, release
the read lock around the subyte operations in mincore. After the lock is reacquired, use the map's timestamp to determine if we need to restart the scan.
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_mmap.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index cda3ee0..974fd00 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.90 1999/02/19 14:25:36 luoqi Exp $
+ * $Id: vm_mmap.c,v 1.91 1999/03/01 20:42:16 alc Exp $
*/
/*
@@ -675,6 +675,7 @@ mincore(p, uap)
register vm_map_entry_t current;
vm_map_entry_t entry;
int mincoreinfo;
+ unsigned int timestamp;
/*
* Make sure that the addresses presented are valid for user
@@ -696,6 +697,8 @@ mincore(p, uap)
pmap = vmspace_pmap(p->p_vmspace);
vm_map_lock_read(map);
+RestartScan:
+ timestamp = map->timestamp;
if (!vm_map_lookup_entry(map, addr, &entry))
entry = entry->next;
@@ -766,6 +769,12 @@ mincore(p, uap)
}
/*
+ * subyte may page fault. In case it needs to modify
+ * the map, we release the lock.
+ */
+ vm_map_unlock_read(map);
+
+ /*
* calculate index into user supplied byte vector
*/
vecindex = OFF_TO_IDX(addr - first_addr);
@@ -777,7 +786,6 @@ mincore(p, uap)
while((lastvecindex + 1) < vecindex) {
error = subyte( vec + lastvecindex, 0);
if (error) {
- vm_map_unlock_read(map);
return (EFAULT);
}
++lastvecindex;
@@ -788,28 +796,49 @@ mincore(p, uap)
*/
error = subyte( vec + vecindex, mincoreinfo);
if (error) {
- vm_map_unlock_read(map);
return (EFAULT);
}
+
+ /*
+ * If the map has changed, due to the subyte, the previous
+ * output may be invalid.
+ */
+ vm_map_lock_read(map);
+ if (timestamp != map->timestamp)
+ goto RestartScan;
+
lastvecindex = vecindex;
addr += PAGE_SIZE;
}
}
/*
+ * subyte may page fault. In case it needs to modify
+ * the map, we release the lock.
+ */
+ vm_map_unlock_read(map);
+
+ /*
* Zero the last entries in the byte vector.
*/
vecindex = OFF_TO_IDX(end - first_addr);
while((lastvecindex + 1) < vecindex) {
error = subyte( vec + lastvecindex, 0);
if (error) {
- vm_map_unlock_read(map);
return (EFAULT);
}
++lastvecindex;
}
+ /*
+ * If the map has changed, due to the subyte, the previous
+ * output may be invalid.
+ */
+ vm_map_lock_read(map);
+ if (timestamp != map->timestamp)
+ goto RestartScan;
vm_map_unlock_read(map);
+
return (0);
}
OpenPOWER on IntegriCloud