Author: bonefish Date: 2010-04-05 13:08:01 +0200 (Mon, 05 Apr 2010) New Revision: 36033 Changeset: http://dev.haiku-os.org/changeset/36033/haiku Ticket: http://dev.haiku-os.org/ticket/5680 Modified: haiku/trunk/headers/private/kernel/vm/VMArea.h haiku/trunk/src/system/kernel/vm/VMArea.cpp haiku/trunk/src/system/kernel/vm/vm.cpp Log: * Removed the VMArea::Wire() version that has to allocate a VMAreaWiredRange. Since the requirement is that the area's top cache is locked, allocating memory isn't allowed. * lock_memory_etc(): Create the VMAreaWiredRange object explicitly before locking the area's top cache. Fixes #5680 (deadlocks when using the slab as malloc() backend). Modified: haiku/trunk/headers/private/kernel/vm/VMArea.h =================================================================== --- haiku/trunk/headers/private/kernel/vm/VMArea.h 2010-04-05 10:46:08 UTC (rev 36032) +++ haiku/trunk/headers/private/kernel/vm/VMArea.h 2010-04-05 11:08:01 UTC (rev 36033) @@ -94,7 +94,6 @@ bool IsWired(addr_t base, size_t size) const; void Wire(VMAreaWiredRange* range); - VMAreaWiredRange* Wire(addr_t base, size_t size, bool writable); void Unwire(VMAreaWiredRange* range); void Unwire(addr_t base, size_t size, bool writable); Modified: haiku/trunk/src/system/kernel/vm/VMArea.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/VMArea.cpp 2010-04-05 10:46:08 UTC (rev 36032) +++ haiku/trunk/src/system/kernel/vm/VMArea.cpp 2010-04-05 11:08:01 UTC (rev 36033) @@ -106,25 +106,6 @@ } -/*! Adds a wired range to this area. - The area's top cache must be locked. - - \return The newly created wired area object. \c NULL when out of memory. -*/ -VMAreaWiredRange* -VMArea::Wire(addr_t base, size_t size, bool writable) -{ - VMAreaWiredRange* range = new(std::nothrow) VMAreaWiredRange(base, size, - writable, true); - if (range == NULL) - return NULL; - - Wire(range); - - return range; -} - - /*! Removes the given wired range from this area. Must balance a previous Wire() call. The area's top cache must be locked. Modified: haiku/trunk/src/system/kernel/vm/vm.cpp =================================================================== --- haiku/trunk/src/system/kernel/vm/vm.cpp 2010-04-05 10:46:08 UTC (rev 36032) +++ haiku/trunk/src/system/kernel/vm/vm.cpp 2010-04-05 11:08:01 UTC (rev 36033) @@ -4792,17 +4792,23 @@ addr_t areaStart = nextAddress; addr_t areaEnd = std::min(lockEndAddress, area->Base() + area->Size()); - // Lock the area's top cache. This is a requirement for VMArea::Wire(). - VMCacheChainLocker cacheChainLocker(vm_area_get_locked_cache(area)); - - // mark the area range wired - VMAreaWiredRange* range = area->Wire(areaStart, areaEnd - areaStart, - writable); + // allocate the wired range (do that before locking the cache to avoid + // deadlocks) + uint32 mallocFlags = isUser + ? 0 : HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE; + VMAreaWiredRange* range = new(malloc_flags(mallocFlags)) + VMAreaWiredRange(areaStart, areaEnd - areaStart, writable, true); if (range == NULL) { error = B_NO_MEMORY; break; } + // Lock the area's top cache. This is a requirement for VMArea::Wire(). + VMCacheChainLocker cacheChainLocker(vm_area_get_locked_cache(area)); + + // mark the area range wired + area->Wire(range); + // Depending on the area cache type and the wiring, we may not need to // look at the individual pages. if (area->cache_type == CACHE_TYPE_NULL