summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_mmap.c
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2010-09-07 00:23:45 +0000
committerrstone <rstone@FreeBSD.org>2010-09-07 00:23:45 +0000
commit0dd3ce30eb28360680a5d3776ec8eb0bf6848bfb (patch)
tree062bb43837887b02bc6b1a1ddbaa6c8666235b4f /sys/vm/vm_mmap.c
parent4701f590b3c86441eea2b3ceb415651be378f742 (diff)
downloadFreeBSD-src-0dd3ce30eb28360680a5d3776ec8eb0bf6848bfb.zip
FreeBSD-src-0dd3ce30eb28360680a5d3776ec8eb0bf6848bfb.tar.gz
In munmap() downgrade the vm_map_lock to a read lock before taking a read
lock on the pmc-sx lock. This prevents a deadlock with pmc_log_process_mappings, which has an exclusive lock on pmc-sx and tries to get a read lock on a vm_map. Downgrading the vm_map_lock in munmap allows pmc_log_process_mappings to continue, preventing the deadlock. Without this change I could cause a deadlock on a multicore 8.1-RELEASE system by having one thread constantly mmap'ing and then munmap'ing a PROT_EXEC mapping in a loop while I repeatedly invoked and stopped pmcstat in system-wide sampling mode. Reviewed by: fabient Approved by: emaste (mentor) MFC after: 2 weeks
Diffstat (limited to 'sys/vm/vm_mmap.c')
-rw-r--r--sys/vm/vm_mmap.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 2071cc7..c912678 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -579,6 +579,7 @@ munmap(td, uap)
* Inform hwpmc if the address range being unmapped contains
* an executable region.
*/
+ pkm.pm_address = (uintptr_t) NULL;
if (vm_map_lookup_entry(map, addr, &entry)) {
for (;
entry != &map->header && entry->start < addr + size;
@@ -587,16 +588,23 @@ munmap(td, uap)
entry->end, VM_PROT_EXECUTE) == TRUE) {
pkm.pm_address = (uintptr_t) addr;
pkm.pm_size = (size_t) size;
- PMC_CALL_HOOK(td, PMC_FN_MUNMAP,
- (void *) &pkm);
break;
}
}
}
#endif
- /* returns nothing but KERN_SUCCESS anyway */
vm_map_delete(map, addr, addr + size);
+
+#ifdef HWPMC_HOOKS
+ /* downgrade the lock to prevent a LOR with the pmc-sx lock */
+ vm_map_lock_downgrade(map);
+ if (pkm.pm_address != (uintptr) NULL)
+ PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
+ vm_map_unlock_read(map);
+#else
vm_map_unlock(map);
+#endif
+ /* vm_map_delete returns nothing but KERN_SUCCESS anyway */
return (0);
}
OpenPOWER on IntegriCloud