diff options
author | alc <alc@FreeBSD.org> | 1999-03-02 22:55:02 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 1999-03-02 22:55:02 +0000 |
commit | 9e3d479b9d7509856e6dc91e1c69dc2e9165b908 (patch) | |
tree | 96191ebe82bd42f9a978ff29e4a0aaa24e86575c /sys/vm | |
parent | 4e5c23f7a19f274c7684cd2771a113f2f2cc6689 (diff) | |
download | FreeBSD-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.c | 37 |
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); } |