* 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). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36033 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -94,7 +94,6 @@ struct VMArea {
|
|||||||
bool IsWired(addr_t base, size_t size) const;
|
bool IsWired(addr_t base, size_t size) const;
|
||||||
|
|
||||||
void Wire(VMAreaWiredRange* range);
|
void Wire(VMAreaWiredRange* range);
|
||||||
VMAreaWiredRange* Wire(addr_t base, size_t size, bool writable);
|
|
||||||
void Unwire(VMAreaWiredRange* range);
|
void Unwire(VMAreaWiredRange* range);
|
||||||
void Unwire(addr_t base, size_t size, bool writable);
|
void Unwire(addr_t base, size_t size, bool writable);
|
||||||
|
|
||||||
|
|||||||
@@ -106,25 +106,6 @@ VMArea::Wire(VMAreaWiredRange* range)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! 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.
|
/*! Removes the given wired range from this area.
|
||||||
Must balance a previous Wire() call.
|
Must balance a previous Wire() call.
|
||||||
The area's top cache must be locked.
|
The area's top cache must be locked.
|
||||||
|
|||||||
@@ -4792,17 +4792,23 @@ lock_memory_etc(team_id team, void* address, size_t numBytes, uint32 flags)
|
|||||||
addr_t areaStart = nextAddress;
|
addr_t areaStart = nextAddress;
|
||||||
addr_t areaEnd = std::min(lockEndAddress, area->Base() + area->Size());
|
addr_t areaEnd = std::min(lockEndAddress, area->Base() + area->Size());
|
||||||
|
|
||||||
// Lock the area's top cache. This is a requirement for VMArea::Wire().
|
// allocate the wired range (do that before locking the cache to avoid
|
||||||
VMCacheChainLocker cacheChainLocker(vm_area_get_locked_cache(area));
|
// deadlocks)
|
||||||
|
uint32 mallocFlags = isUser
|
||||||
// mark the area range wired
|
? 0 : HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
VMAreaWiredRange* range = area->Wire(areaStart, areaEnd - areaStart,
|
VMAreaWiredRange* range = new(malloc_flags(mallocFlags))
|
||||||
writable);
|
VMAreaWiredRange(areaStart, areaEnd - areaStart, writable, true);
|
||||||
if (range == NULL) {
|
if (range == NULL) {
|
||||||
error = B_NO_MEMORY;
|
error = B_NO_MEMORY;
|
||||||
break;
|
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
|
// Depending on the area cache type and the wiring, we may not need to
|
||||||
// look at the individual pages.
|
// look at the individual pages.
|
||||||
if (area->cache_type == CACHE_TYPE_NULL
|
if (area->cache_type == CACHE_TYPE_NULL
|
||||||
|
|||||||
Reference in New Issue
Block a user