svn commit: r212281 - head/sys/vm
Kostik Belousov
kostikbel at gmail.com
Tue Sep 7 08:04:51 UTC 2010
On Tue, Sep 07, 2010 at 12:23:45AM +0000, Ryan Stone wrote:
> Author: rstone
> Date: Tue Sep 7 00:23:45 2010
> New Revision: 212281
> URL: http://svn.freebsd.org/changeset/base/212281
>
> Log:
> 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
>
> Modified:
> head/sys/vm/vm_mmap.c
>
> Modified: head/sys/vm/vm_mmap.c
> ==============================================================================
> --- head/sys/vm/vm_mmap.c Mon Sep 6 23:52:04 2010 (r212280)
> +++ head/sys/vm/vm_mmap.c Tue Sep 7 00:23:45 2010 (r212281)
> @@ -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);
> }
>
Note that vm_map_unlock() is more then just dropping the lock on the map.
Due to ordering of the vnode lock before vm map lock, vm_map_unlock()
processes the deferred free entries after map lock is dropped. After your
change, the deferred list might keep entries for some time until next
unlock is performed.
I think the two changes could be done:
- only perform downgrade when hook is indeed going to be called;
- before vm_map_unlock_read, check for deferred_freelist being not
NULL, and if so, do vm_map_lock()/vm_map_unlock() after unlock_read.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/svn-src-head/attachments/20100907/a42e76b6/attachment.pgp
More information about the svn-src-head
mailing list