* Introduced {malloc,memalign,free}_etc() which take an additional "flags"
argument. They replace the previous special-purpose allocation functions (malloc_nogrow(), vip_io_request_malloc()). * Moved the I/O VIP heap to heap.cpp accordingly. * Added quite a bit of passing around of allocation flags in the VM, particularly in the VM*AddressSpace classes. * Fixed IOBuffer::GetNextVirtualVec(): It was ignoring the VIP flag and always allocated on the normal heap. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35316 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,6 +23,12 @@
|
|||||||
#define HEAP_AREA_USE_THRESHOLD 1 * 1024 * 1024
|
#define HEAP_AREA_USE_THRESHOLD 1 * 1024 * 1024
|
||||||
|
|
||||||
|
|
||||||
|
// allocation/deallocation flags for {malloc,free}_etc()
|
||||||
|
#define HEAP_DONT_WAIT_FOR_MEMORY 0x01
|
||||||
|
#define HEAP_DONT_LOCK_KERNEL_SPACE 0x02
|
||||||
|
#define HEAP_PRIORITY_VIP 0x04
|
||||||
|
|
||||||
|
|
||||||
typedef struct heap_class_s {
|
typedef struct heap_class_s {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint32 initial_percentage;
|
uint32 initial_percentage;
|
||||||
@@ -41,10 +47,9 @@ typedef struct heap_allocator_s heap_allocator;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// malloc- and memalign_nogrow disallow waiting for a grow to happen - only to
|
|
||||||
// be used by vm functions that may deadlock on a triggered area creation.
|
void* memalign_etc(size_t alignment, size_t size, uint32 flags);
|
||||||
void* memalign_nogrow(size_t alignment, size_t size);
|
void free_etc(void* address, uint32 flags);
|
||||||
void* malloc_nogrow(size_t size);
|
|
||||||
|
|
||||||
void* memalign(size_t alignment, size_t size);
|
void* memalign(size_t alignment, size_t size);
|
||||||
|
|
||||||
@@ -74,6 +79,13 @@ status_t heap_init_post_thread();
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static inline void*
|
||||||
|
malloc_etc(size_t size, uint32 flags)
|
||||||
|
{
|
||||||
|
return memalign_etc(0, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -81,21 +93,34 @@ status_t heap_init_post_thread();
|
|||||||
#include <util/SinglyLinkedList.h>
|
#include <util/SinglyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
static const struct nogrow_t {
|
struct malloc_flags {
|
||||||
} nogrow = {};
|
uint32 flags;
|
||||||
|
|
||||||
|
malloc_flags(uint32 flags)
|
||||||
|
:
|
||||||
|
flags(flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
malloc_flags(const malloc_flags& other)
|
||||||
|
:
|
||||||
|
flags(other.flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
inline void*
|
inline void*
|
||||||
operator new(size_t size, const nogrow_t& nogrow) throw()
|
operator new(size_t size, const malloc_flags& flags) throw()
|
||||||
{
|
{
|
||||||
return malloc_nogrow(size);
|
return malloc_etc(size, flags.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void*
|
inline void*
|
||||||
operator new[](size_t size, const nogrow_t& nogrow) throw()
|
operator new[](size_t size, const malloc_flags& flags) throw()
|
||||||
{
|
{
|
||||||
return malloc_nogrow(size);
|
return malloc_etc(size, flags.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,24 +8,26 @@
|
|||||||
#define _SLAB_SLAB_H_
|
#define _SLAB_SLAB_H_
|
||||||
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <heap.h>
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* create_object_cache_etc flags */
|
/* object_cache_{alloc,free}() flags */
|
||||||
CACHE_NO_DEPOT = 1 << 0,
|
CACHE_DONT_WAIT_FOR_MEMORY = HEAP_DONT_WAIT_FOR_MEMORY,
|
||||||
CACHE_UNLOCKED_PAGES = 1 << 1, // unsupported
|
CACHE_DONT_LOCK_KERNEL_SPACE = HEAP_DONT_LOCK_KERNEL_SPACE,
|
||||||
CACHE_LARGE_SLAB = 1 << 2,
|
CACHE_PRIORITY_VIP = HEAP_PRIORITY_VIP,
|
||||||
|
CACHE_ALLOC_FLAGS = CACHE_DONT_WAIT_FOR_MEMORY
|
||||||
|
| CACHE_DONT_LOCK_KERNEL_SPACE
|
||||||
|
| CACHE_PRIORITY_VIP,
|
||||||
|
|
||||||
/* object_cache_{alloc,free}() flags */
|
/* create_object_cache_etc flags */
|
||||||
CACHE_DONT_WAIT_FOR_MEMORY = 1 << 8,
|
CACHE_NO_DEPOT = 0x08000000,
|
||||||
CACHE_DONT_LOCK_KERNEL_SPACE = 1 << 9,
|
CACHE_UNLOCKED_PAGES = 0x10000000, // unsupported
|
||||||
CACHE_PRIORITY_VIP = 1 << 10,
|
CACHE_LARGE_SLAB = 0x20000000,
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
CACHE_ALIGN_ON_SIZE = 1 << 30,
|
CACHE_ALIGN_ON_SIZE = 0x40000000,
|
||||||
CACHE_DURING_BOOT = 1 << 31
|
CACHE_DURING_BOOT = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ObjectCache;
|
struct ObjectCache;
|
||||||
|
|||||||
@@ -289,8 +289,6 @@ public:
|
|||||||
bool partialTransfer,
|
bool partialTransfer,
|
||||||
size_t bytesTransferred) = 0;
|
size_t bytesTransferred) = 0;
|
||||||
|
|
||||||
void operator delete(void* address, size_t size);
|
|
||||||
|
|
||||||
static status_t IORequestCallback(void* data,
|
static status_t IORequestCallback(void* data,
|
||||||
io_request* request, status_t status,
|
io_request* request, status_t status,
|
||||||
bool partialTransfer,
|
bool partialTransfer,
|
||||||
|
|||||||
@@ -70,25 +70,31 @@ public:
|
|||||||
|
|
||||||
virtual VMArea* LookupArea(addr_t address) const = 0;
|
virtual VMArea* LookupArea(addr_t address) const = 0;
|
||||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||||
uint32 protection) = 0;
|
uint32 protection,
|
||||||
virtual void DeleteArea(VMArea* area) = 0;
|
uint32 allocationFlags) = 0;
|
||||||
|
virtual void DeleteArea(VMArea* area,
|
||||||
|
uint32 allocationFlags) = 0;
|
||||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||||
size_t size, VMArea* area) = 0;
|
size_t size, VMArea* area,
|
||||||
virtual void RemoveArea(VMArea* area) = 0;
|
uint32 allocationFlags) = 0;
|
||||||
|
virtual void RemoveArea(VMArea* area,
|
||||||
|
uint32 allocationFlags) = 0;
|
||||||
|
|
||||||
virtual bool CanResizeArea(VMArea* area, size_t newSize) = 0;
|
virtual bool CanResizeArea(VMArea* area, size_t newSize) = 0;
|
||||||
virtual status_t ResizeArea(VMArea* area, size_t newSize) = 0;
|
virtual status_t ResizeArea(VMArea* area, size_t newSize,
|
||||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize)
|
uint32 allocationFlags) = 0;
|
||||||
= 0;
|
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize,
|
||||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize)
|
uint32 allocationFlags) = 0;
|
||||||
= 0;
|
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags) = 0;
|
||||||
|
|
||||||
virtual status_t ReserveAddressRange(void** _address,
|
virtual status_t ReserveAddressRange(void** _address,
|
||||||
uint32 addressSpec, size_t size,
|
uint32 addressSpec, size_t size,
|
||||||
uint32 flags) = 0;
|
uint32 flags, uint32 allocationFlags) = 0;
|
||||||
virtual status_t UnreserveAddressRange(addr_t address,
|
virtual status_t UnreserveAddressRange(addr_t address,
|
||||||
size_t size) = 0;
|
size_t size, uint32 allocationFlags) = 0;
|
||||||
virtual void UnreserveAllAddressRanges() = 0;
|
virtual void UnreserveAllAddressRanges(
|
||||||
|
uint32 allocationFlags) = 0;
|
||||||
|
|
||||||
virtual void Dump() const;
|
virtual void Dump() const;
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ protected:
|
|||||||
uint32 wiring, uint32 protection);
|
uint32 wiring, uint32 protection);
|
||||||
~VMArea();
|
~VMArea();
|
||||||
|
|
||||||
status_t Init(const char* name);
|
status_t Init(const char* name, uint32 allocationFlags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class VMAddressSpace;
|
friend class VMAddressSpace;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
VMCache();
|
VMCache();
|
||||||
virtual ~VMCache();
|
virtual ~VMCache();
|
||||||
|
|
||||||
status_t Init(uint32 cacheType);
|
status_t Init(uint32 cacheType, uint32 allocationFlags);
|
||||||
|
|
||||||
virtual void Delete();
|
virtual void Delete();
|
||||||
|
|
||||||
|
|||||||
@@ -1369,7 +1369,7 @@ m68k_vm_translation_map_init_post_area(kernel_args *args)
|
|||||||
|
|
||||||
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
||||||
"interrupt query pages", (void **)&queryPage, B_ANY_ADDRESS,
|
"interrupt query pages", (void **)&queryPage, B_ANY_ADDRESS,
|
||||||
B_PAGE_SIZE, CREATE_AREA_PRIORITY_VIP);
|
B_PAGE_SIZE, 0);
|
||||||
if (area < B_OK)
|
if (area < B_OK)
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ LargeMemoryPhysicalPageMapper::InitPostArea(kernel_args* args)
|
|||||||
temp = (void*)fInitialPool.virtualBase;
|
temp = (void*)fInitialPool.virtualBase;
|
||||||
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
area = vm_create_null_area(VMAddressSpace::KernelID(),
|
||||||
"physical page pool space", &temp, B_EXACT_ADDRESS,
|
"physical page pool space", &temp, B_EXACT_ADDRESS,
|
||||||
1024 * B_PAGE_SIZE, CREATE_AREA_PRIORITY_VIP);
|
1024 * B_PAGE_SIZE, 0);
|
||||||
if (area < B_OK) {
|
if (area < B_OK) {
|
||||||
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
panic("LargeMemoryPhysicalPageMapper::InitPostArea(): Failed to "
|
||||||
"create area for physical page pool space.");
|
"create area for physical page pool space.");
|
||||||
|
|||||||
+2
-2
@@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMVnodeCache::Init(struct vnode *vnode)
|
VMVnodeCache::Init(struct vnode *vnode, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
status_t error = VMCache::Init(CACHE_TYPE_VNODE);
|
status_t error = VMCache::Init(CACHE_TYPE_VNODE, allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ struct file_cache_ref;
|
|||||||
|
|
||||||
class VMVnodeCache : public VMCache {
|
class VMVnodeCache : public VMCache {
|
||||||
public:
|
public:
|
||||||
status_t Init(struct vnode *vnode);
|
status_t Init(struct vnode *vnode, uint32 allocationFlags);
|
||||||
|
|
||||||
virtual bool HasPage(off_t offset);
|
virtual bool HasPage(off_t offset);
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define VIP_HEAP_SIZE 1024 * 1024
|
|
||||||
|
|
||||||
// partial I/O operation phases
|
// partial I/O operation phases
|
||||||
enum {
|
enum {
|
||||||
PHASE_READ_BEGIN = 0,
|
PHASE_READ_BEGIN = 0,
|
||||||
@@ -37,8 +35,6 @@ enum {
|
|||||||
PHASE_DO_ALL = 2
|
PHASE_DO_ALL = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
heap_allocator* sVIPHeap;
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
@@ -56,13 +52,6 @@ IORequestChunk::~IORequestChunk()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
IORequestChunk::operator delete(void* address, size_t size)
|
|
||||||
{
|
|
||||||
io_request_free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +69,7 @@ IOBuffer::Create(uint32 count, bool vip)
|
|||||||
{
|
{
|
||||||
size_t size = sizeof(IOBuffer) + sizeof(iovec) * (count - 1);
|
size_t size = sizeof(IOBuffer) + sizeof(iovec) * (count - 1);
|
||||||
IOBuffer* buffer
|
IOBuffer* buffer
|
||||||
= (IOBuffer*)(vip ? vip_io_request_malloc(size) : malloc(size));
|
= (IOBuffer*)(malloc_etc(size, vip ? HEAP_PRIORITY_VIP : 0));
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -101,10 +90,7 @@ IOBuffer::Delete()
|
|||||||
if (this == NULL)
|
if (this == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fVIP)
|
free_etc(this, fVIP ? HEAP_PRIORITY_VIP : 0);
|
||||||
vip_io_request_free(this);
|
|
||||||
else
|
|
||||||
free(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +116,8 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
|
|||||||
{
|
{
|
||||||
virtual_vec_cookie* cookie = (virtual_vec_cookie*)_cookie;
|
virtual_vec_cookie* cookie = (virtual_vec_cookie*)_cookie;
|
||||||
if (cookie == NULL) {
|
if (cookie == NULL) {
|
||||||
cookie = new(std::nothrow) virtual_vec_cookie;
|
cookie = new(malloc_flags(fVIP ? HEAP_PRIORITY_VIP : 0))
|
||||||
|
virtual_vec_cookie;
|
||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -207,7 +194,7 @@ IOBuffer::FreeVirtualVecCookie(void* _cookie)
|
|||||||
if (cookie->mapped_area >= 0)
|
if (cookie->mapped_area >= 0)
|
||||||
delete_area(cookie->mapped_area);
|
delete_area(cookie->mapped_area);
|
||||||
|
|
||||||
delete cookie;
|
free_etc(cookie, fVIP ? HEAP_PRIORITY_VIP : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -715,7 +702,9 @@ IORequest::~IORequest()
|
|||||||
/* static */ IORequest*
|
/* static */ IORequest*
|
||||||
IORequest::Create(bool vip)
|
IORequest::Create(bool vip)
|
||||||
{
|
{
|
||||||
return vip ? new(vip_io_alloc) IORequest : new(std::nothrow) IORequest;
|
return vip
|
||||||
|
? new(malloc_flags(HEAP_PRIORITY_VIP)) IORequest
|
||||||
|
: new(std::nothrow) IORequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1309,106 +1298,3 @@ IORequest::Dump() const
|
|||||||
set_debug_variable("_buffer", (addr_t)fBuffer);
|
set_debug_variable("_buffer", (addr_t)fBuffer);
|
||||||
set_debug_variable("_cvar", (addr_t)&fFinishedCondition);
|
set_debug_variable("_cvar", (addr_t)&fFinishedCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - allocator
|
|
||||||
|
|
||||||
|
|
||||||
#if KERNEL_HEAP_LEAK_CHECK
|
|
||||||
static addr_t
|
|
||||||
get_caller()
|
|
||||||
{
|
|
||||||
// Find the first return address outside of the allocator code. Note, that
|
|
||||||
// this makes certain assumptions about how the code for the functions
|
|
||||||
// ends up in the kernel object.
|
|
||||||
addr_t returnAddresses[5];
|
|
||||||
int32 depth = arch_debug_get_stack_trace(returnAddresses, 5, 0, 1,
|
|
||||||
STACK_TRACE_KERNEL | STACK_TRACE_USER);
|
|
||||||
|
|
||||||
// find the first return address inside the VIP allocator
|
|
||||||
int32 i = 0;
|
|
||||||
for (i = 0; i < depth; i++) {
|
|
||||||
if (returnAddresses[i] >= (addr_t)&get_caller
|
|
||||||
&& returnAddresses[i] < (addr_t)&vip_io_request_allocator_init) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now continue until we have the first one outside
|
|
||||||
for (; i < depth; i++) {
|
|
||||||
if (returnAddresses[i] < (addr_t)&get_caller
|
|
||||||
|| returnAddresses[i] > (addr_t)&vip_io_request_allocator_init) {
|
|
||||||
return returnAddresses[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void*
|
|
||||||
vip_io_request_malloc(size_t size)
|
|
||||||
{
|
|
||||||
void* address = heap_memalign(sVIPHeap, 0, size);
|
|
||||||
#if KDEBUG
|
|
||||||
if (address == NULL)
|
|
||||||
panic("vip_io_request_malloc(): VIP heap %p out of memory", sVIPHeap);
|
|
||||||
#endif
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
vip_io_request_free(void* address)
|
|
||||||
{
|
|
||||||
heap_free(sVIPHeap, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
io_request_free(void* address)
|
|
||||||
{
|
|
||||||
if (heap_free(sVIPHeap, address) != B_OK)
|
|
||||||
free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
vip_io_request_allocator_init()
|
|
||||||
{
|
|
||||||
static const heap_class heapClass = {
|
|
||||||
"VIP I/O", /* name */
|
|
||||||
100, /* initial percentage */
|
|
||||||
B_PAGE_SIZE / 8, /* max allocation size */
|
|
||||||
B_PAGE_SIZE, /* page size */
|
|
||||||
8, /* min bin size */
|
|
||||||
4, /* bin alignment */
|
|
||||||
8, /* min count per page */
|
|
||||||
16 /* max waste per page */
|
|
||||||
};
|
|
||||||
|
|
||||||
void* address = NULL;
|
|
||||||
area_id area = create_area("VIP I/O heap", &address, B_ANY_KERNEL_ADDRESS,
|
|
||||||
VIP_HEAP_SIZE, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
|
||||||
if (area < B_OK) {
|
|
||||||
panic("vip_io_request_allocator_init(): couldn't allocate VIP I/O "
|
|
||||||
"heap area");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sVIPHeap = heap_create_allocator("VIP I/O heap", (addr_t)address,
|
|
||||||
VIP_HEAP_SIZE, &heapClass, false);
|
|
||||||
if (sVIPHeap == NULL) {
|
|
||||||
panic("vip_io_request_allocator_init(): failed to create VIP I/O "
|
|
||||||
"heap\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if KERNEL_HEAP_LEAK_CHECK
|
|
||||||
heap_set_get_caller(sVIPHeap, &get_caller);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dprintf("vip_io_request_allocator_init(): created VIP I/O heap: %p\n",
|
|
||||||
sVIPHeap);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -102,8 +102,6 @@ public:
|
|||||||
DoublyLinkedListLink<IORequestChunk>*
|
DoublyLinkedListLink<IORequestChunk>*
|
||||||
ListLink() { return &fListLink; }
|
ListLink() { return &fListLink; }
|
||||||
|
|
||||||
void operator delete(void* address, size_t size);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetStatus(status_t status)
|
void SetStatus(status_t status)
|
||||||
{ fStatus = status; }
|
{ fStatus = status; }
|
||||||
@@ -352,33 +350,4 @@ private:
|
|||||||
typedef DoublyLinkedList<IORequest> IORequestList;
|
typedef DoublyLinkedList<IORequest> IORequestList;
|
||||||
|
|
||||||
|
|
||||||
// allocator for VIP I/O request memory
|
|
||||||
void* vip_io_request_malloc(size_t size);
|
|
||||||
void vip_io_request_free(void* address);
|
|
||||||
|
|
||||||
void io_request_free(void* address);
|
|
||||||
// frees regardless of whether allocated with vip_io_request_malloc() or
|
|
||||||
// malloc()
|
|
||||||
|
|
||||||
void vip_io_request_allocator_init();
|
|
||||||
|
|
||||||
|
|
||||||
static const struct vip_io_alloc_t {
|
|
||||||
} vip_io_alloc = {};
|
|
||||||
|
|
||||||
|
|
||||||
inline void*
|
|
||||||
operator new(size_t size, const vip_io_alloc_t& vip_io_alloc) throw ()
|
|
||||||
{
|
|
||||||
return vip_io_request_malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void*
|
|
||||||
operator new[](size_t size, const vip_io_alloc_t& vip_io_alloc) throw ()
|
|
||||||
{
|
|
||||||
return vip_io_request_malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // IO_REQUEST_H
|
#endif // IO_REQUEST_H
|
||||||
|
|||||||
@@ -2257,7 +2257,6 @@ device_manager_init(struct kernel_args* args)
|
|||||||
{
|
{
|
||||||
TRACE(("device manager init\n"));
|
TRACE(("device manager init\n"));
|
||||||
|
|
||||||
vip_io_request_allocator_init();
|
|
||||||
IOSchedulerRoster::Init();
|
IOSchedulerRoster::Init();
|
||||||
|
|
||||||
dm_init_id_generator();
|
dm_init_id_generator();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,6 +14,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <heap.h>
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - AsyncIOCallback
|
// #pragma mark - AsyncIOCallback
|
||||||
|
|
||||||
|
|
||||||
@@ -22,13 +25,6 @@ AsyncIOCallback::~AsyncIOCallback()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
AsyncIOCallback::operator delete(void* address, size_t size)
|
|
||||||
{
|
|
||||||
io_request_free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* static */ status_t
|
/* static */ status_t
|
||||||
AsyncIOCallback::IORequestCallback(void* data, io_request* request,
|
AsyncIOCallback::IORequestCallback(void* data, io_request* request,
|
||||||
status_t status, bool partialTransfer, size_t transferEndOffset)
|
status_t status, bool partialTransfer, size_t transferEndOffset)
|
||||||
@@ -61,9 +57,6 @@ struct iterative_io_cookie {
|
|||||||
off_t request_offset;
|
off_t request_offset;
|
||||||
io_request_finished_callback next_finished_callback;
|
io_request_finished_callback next_finished_callback;
|
||||||
void* next_finished_cookie;
|
void* next_finished_cookie;
|
||||||
|
|
||||||
void operator delete(void* address, size_t size)
|
|
||||||
{ io_request_free(address); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -484,7 +477,7 @@ do_iterative_fd_io(int fd, io_request* request, iterative_io_get_vecs getVecs,
|
|||||||
|
|
||||||
iterative_io_cookie* iterationCookie
|
iterative_io_cookie* iterationCookie
|
||||||
= (request->Flags() & B_VIP_IO_REQUEST) != 0
|
= (request->Flags() & B_VIP_IO_REQUEST) != 0
|
||||||
? new(vip_io_alloc) iterative_io_cookie
|
? new(malloc_flags(HEAP_PRIORITY_VIP)) iterative_io_cookie
|
||||||
: new(std::nothrow) iterative_io_cookie;
|
: new(std::nothrow) iterative_io_cookie;
|
||||||
if (iterationCookie == NULL) {
|
if (iterationCookie == NULL) {
|
||||||
// no memory -- fall back to synchronous I/O
|
// no memory -- fall back to synchronous I/O
|
||||||
|
|||||||
+135
-61
@@ -142,6 +142,10 @@ typedef SinglyLinkedList<DeferredFreeListEntry> DeferredFreeList;
|
|||||||
typedef SinglyLinkedList<DeferredDeletable> DeferredDeletableList;
|
typedef SinglyLinkedList<DeferredDeletable> DeferredDeletableList;
|
||||||
|
|
||||||
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
#define VIP_HEAP_SIZE 1024 * 1024
|
||||||
|
|
||||||
// Heap class configuration
|
// Heap class configuration
|
||||||
#define HEAP_CLASS_COUNT 3
|
#define HEAP_CLASS_COUNT 3
|
||||||
static heap_class sHeapClasses[HEAP_CLASS_COUNT] = {
|
static heap_class sHeapClasses[HEAP_CLASS_COUNT] = {
|
||||||
@@ -183,11 +187,15 @@ static heap_allocator *sHeaps[HEAP_CLASS_COUNT * B_MAX_CPU_COUNT];
|
|||||||
static uint32 *sLastGrowRequest[HEAP_CLASS_COUNT * B_MAX_CPU_COUNT];
|
static uint32 *sLastGrowRequest[HEAP_CLASS_COUNT * B_MAX_CPU_COUNT];
|
||||||
static uint32 *sLastHandledGrowRequest[HEAP_CLASS_COUNT * B_MAX_CPU_COUNT];
|
static uint32 *sLastHandledGrowRequest[HEAP_CLASS_COUNT * B_MAX_CPU_COUNT];
|
||||||
|
|
||||||
|
static heap_allocator *sVIPHeap;
|
||||||
static heap_allocator *sGrowHeap = NULL;
|
static heap_allocator *sGrowHeap = NULL;
|
||||||
static thread_id sHeapGrowThread = -1;
|
static thread_id sHeapGrowThread = -1;
|
||||||
static sem_id sHeapGrowSem = -1;
|
static sem_id sHeapGrowSem = -1;
|
||||||
static sem_id sHeapGrownNotify = -1;
|
static sem_id sHeapGrownNotify = -1;
|
||||||
static bool sAddGrowHeap = false;
|
static bool sAddGrowHeap = false;
|
||||||
|
|
||||||
|
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
static DeferredFreeList sDeferredFreeList;
|
static DeferredFreeList sDeferredFreeList;
|
||||||
static DeferredDeletableList sDeferredDeletableList;
|
static DeferredDeletableList sDeferredDeletableList;
|
||||||
static spinlock sDeferredFreeListLock;
|
static spinlock sDeferredFreeListLock;
|
||||||
@@ -271,6 +279,9 @@ class Free : public AbstractTraceEntry {
|
|||||||
// #pragma mark - Debug functions
|
// #pragma mark - Debug functions
|
||||||
|
|
||||||
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
|
||||||
#if KERNEL_HEAP_LEAK_CHECK
|
#if KERNEL_HEAP_LEAK_CHECK
|
||||||
static addr_t
|
static addr_t
|
||||||
get_caller()
|
get_caller()
|
||||||
@@ -809,6 +820,8 @@ dump_allocations_per_caller(int argc, char **argv)
|
|||||||
|
|
||||||
#endif // KERNEL_HEAP_LEAK_CHECK
|
#endif // KERNEL_HEAP_LEAK_CHECK
|
||||||
|
|
||||||
|
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
|
||||||
#if PARANOID_HEAP_VALIDATION
|
#if PARANOID_HEAP_VALIDATION
|
||||||
static void
|
static void
|
||||||
@@ -1797,9 +1810,6 @@ heap_realloc(heap_allocator *heap, void *address, void **newAddress,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
|
||||||
|
|
||||||
|
|
||||||
inline uint32
|
inline uint32
|
||||||
heap_index_for(size_t size, int32 cpu)
|
heap_index_for(size_t size, int32 cpu)
|
||||||
{
|
{
|
||||||
@@ -1818,35 +1828,47 @@ heap_index_for(size_t size, int32 cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void *
|
||||||
deferred_deleter(void *arg, int iteration)
|
memalign_nogrow(size_t alignment, size_t size)
|
||||||
{
|
{
|
||||||
// move entries and deletables to on-stack lists
|
// use dedicated memory in the grow thread by default
|
||||||
InterruptsSpinLocker locker(sDeferredFreeListLock);
|
if (thread_get_current_thread_id() == sHeapGrowThread) {
|
||||||
if (sDeferredFreeList.IsEmpty() && sDeferredDeletableList.IsEmpty())
|
void *result = heap_memalign(sGrowHeap, alignment, size);
|
||||||
return;
|
if (!sAddGrowHeap && heap_should_grow(sGrowHeap)) {
|
||||||
|
// hopefully the heap grower will manage to create a new heap
|
||||||
|
// before running out of private memory...
|
||||||
|
dprintf("heap: requesting new grow heap\n");
|
||||||
|
sAddGrowHeap = true;
|
||||||
|
release_sem_etc(sHeapGrowSem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
|
}
|
||||||
|
|
||||||
DeferredFreeList entries;
|
if (result != NULL)
|
||||||
entries.MoveFrom(&sDeferredFreeList);
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DeferredDeletableList deletables;
|
// try public memory, there might be something available
|
||||||
deletables.MoveFrom(&sDeferredDeletableList);
|
void *result = NULL;
|
||||||
|
int32 cpuCount = MIN(smp_get_num_cpus(),
|
||||||
|
(int32)sHeapCount / HEAP_CLASS_COUNT);
|
||||||
|
int32 cpuNumber = smp_get_current_cpu();
|
||||||
|
for (int32 i = 0; i < cpuCount; i++) {
|
||||||
|
uint32 heapIndex = heap_index_for(size, cpuNumber++ % cpuCount);
|
||||||
|
heap_allocator *heap = sHeaps[heapIndex];
|
||||||
|
result = heap_memalign(heap, alignment, size);
|
||||||
|
if (result != NULL)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
locker.Unlock();
|
// no memory available
|
||||||
|
if (thread_get_current_thread_id() == sHeapGrowThread)
|
||||||
|
panic("heap: all heaps have run out of memory while growing\n");
|
||||||
|
else
|
||||||
|
dprintf("heap: all heaps have run out of memory\n");
|
||||||
|
|
||||||
// free the entries
|
return NULL;
|
||||||
while (DeferredFreeListEntry* entry = entries.RemoveHead())
|
|
||||||
free(entry);
|
|
||||||
|
|
||||||
// delete the deletables
|
|
||||||
while (DeferredDeletable* deletable = deletables.RemoveHead())
|
|
||||||
delete deletable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
heap_create_new_heap_area(heap_allocator *heap, const char *name, size_t size)
|
heap_create_new_heap_area(heap_allocator *heap, const char *name, size_t size)
|
||||||
{
|
{
|
||||||
@@ -1907,6 +1929,41 @@ heap_grow_thread(void *)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
deferred_deleter(void *arg, int iteration)
|
||||||
|
{
|
||||||
|
// move entries and deletables to on-stack lists
|
||||||
|
InterruptsSpinLocker locker(sDeferredFreeListLock);
|
||||||
|
if (sDeferredFreeList.IsEmpty() && sDeferredDeletableList.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DeferredFreeList entries;
|
||||||
|
entries.MoveFrom(&sDeferredFreeList);
|
||||||
|
|
||||||
|
DeferredDeletableList deletables;
|
||||||
|
deletables.MoveFrom(&sDeferredDeletableList);
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
// free the entries
|
||||||
|
while (DeferredFreeListEntry* entry = entries.RemoveHead())
|
||||||
|
free(entry);
|
||||||
|
|
||||||
|
// delete the deletables
|
||||||
|
while (DeferredDeletable* deletable = deletables.RemoveHead())
|
||||||
|
delete deletable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
heap_init(addr_t base, size_t size)
|
heap_init(addr_t base, size_t size)
|
||||||
{
|
{
|
||||||
@@ -1988,9 +2045,13 @@ heap_init_post_sem()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
heap_init_post_thread()
|
heap_init_post_thread()
|
||||||
{
|
{
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
void *address = NULL;
|
void *address = NULL;
|
||||||
area_id growHeapArea = create_area("dedicated grow heap", &address,
|
area_id growHeapArea = create_area("dedicated grow heap", &address,
|
||||||
B_ANY_KERNEL_BLOCK_ADDRESS, HEAP_DEDICATED_GROW_SIZE, B_FULL_LOCK,
|
B_ANY_KERNEL_BLOCK_ADDRESS, HEAP_DEDICATED_GROW_SIZE, B_FULL_LOCK,
|
||||||
@@ -2039,11 +2100,43 @@ heap_init_post_thread()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create the VIP heap
|
||||||
|
static const heap_class heapClass = {
|
||||||
|
"VIP I/O", /* name */
|
||||||
|
100, /* initial percentage */
|
||||||
|
B_PAGE_SIZE / 8, /* max allocation size */
|
||||||
|
B_PAGE_SIZE, /* page size */
|
||||||
|
8, /* min bin size */
|
||||||
|
4, /* bin alignment */
|
||||||
|
8, /* min count per page */
|
||||||
|
16 /* max waste per page */
|
||||||
|
};
|
||||||
|
|
||||||
|
area_id vipHeapArea = create_area("VIP heap", &address,
|
||||||
|
B_ANY_KERNEL_ADDRESS, VIP_HEAP_SIZE, B_FULL_LOCK,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
if (vipHeapArea < 0) {
|
||||||
|
panic("heap_init_post_thread(): couldn't allocate VIP heap area");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sVIPHeap = heap_create_allocator("VIP heap", (addr_t)address,
|
||||||
|
VIP_HEAP_SIZE, &heapClass, false);
|
||||||
|
if (sVIPHeap == NULL) {
|
||||||
|
panic("heap_init_post_thread(): failed to create VIP heap\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("heap_init_post_thread(): created VIP heap: %p\n", sVIPHeap);
|
||||||
|
|
||||||
|
send_signal_etc(sHeapGrowThread, SIGCONT, B_DO_NOT_RESCHEDULE);
|
||||||
|
|
||||||
|
#endif // !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
|
||||||
// run the deferred deleter roughly once a second
|
// run the deferred deleter roughly once a second
|
||||||
if (register_kernel_daemon(deferred_deleter, NULL, 10) != B_OK)
|
if (register_kernel_daemon(deferred_deleter, NULL, 10) != B_OK)
|
||||||
panic("heap_init_post_thread(): failed to init deferred deleter");
|
panic("heap_init_post_thread(): failed to init deferred deleter");
|
||||||
|
|
||||||
send_signal_etc(sHeapGrowThread, SIGCONT, B_DO_NOT_RESCHEDULE);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2148,50 +2241,27 @@ memalign(size_t alignment, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
memalign_nogrow(size_t alignment, size_t size)
|
memalign_etc(size_t alignment, size_t size, uint32 flags)
|
||||||
{
|
{
|
||||||
// use dedicated memory in the grow thread by default
|
if ((flags & HEAP_PRIORITY_VIP) != 0)
|
||||||
if (thread_get_current_thread_id() == sHeapGrowThread) {
|
return heap_memalign(sVIPHeap, alignment, size);
|
||||||
void *result = heap_memalign(sGrowHeap, alignment, size);
|
|
||||||
if (!sAddGrowHeap && heap_should_grow(sGrowHeap)) {
|
|
||||||
// hopefully the heap grower will manage to create a new heap
|
|
||||||
// before running out of private memory...
|
|
||||||
dprintf("heap: requesting new grow heap\n");
|
|
||||||
sAddGrowHeap = true;
|
|
||||||
release_sem_etc(sHeapGrowSem, 1, B_DO_NOT_RESCHEDULE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != NULL)
|
if ((flags & (HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE))
|
||||||
return result;
|
!= 0) {
|
||||||
|
return memalign_nogrow(alignment, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try public memory, there might be something available
|
return memalign(alignment, size);
|
||||||
void *result = NULL;
|
|
||||||
int32 cpuCount = MIN(smp_get_num_cpus(),
|
|
||||||
(int32)sHeapCount / HEAP_CLASS_COUNT);
|
|
||||||
int32 cpuNumber = smp_get_current_cpu();
|
|
||||||
for (int32 i = 0; i < cpuCount; i++) {
|
|
||||||
uint32 heapIndex = heap_index_for(size, cpuNumber++ % cpuCount);
|
|
||||||
heap_allocator *heap = sHeaps[heapIndex];
|
|
||||||
result = heap_memalign(heap, alignment, size);
|
|
||||||
if (result != NULL)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no memory available
|
|
||||||
if (thread_get_current_thread_id() == sHeapGrowThread)
|
|
||||||
panic("heap: all heaps have run out of memory while growing\n");
|
|
||||||
else
|
|
||||||
dprintf("heap: all heaps have run out of memory\n");
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
void
|
||||||
malloc_nogrow(size_t size)
|
free_etc(void *address, uint32 flags)
|
||||||
{
|
{
|
||||||
return memalign_nogrow(0, size);
|
if ((flags & HEAP_PRIORITY_VIP) != 0)
|
||||||
|
heap_free(sVIPHeap, address);
|
||||||
|
else
|
||||||
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2225,6 +2295,10 @@ free(void *address)
|
|||||||
if (heap_free(sGrowHeap, address) == B_OK)
|
if (heap_free(sGrowHeap, address) == B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// or maybe it was allocated from the VIP heap
|
||||||
|
if (heap_free(sVIPHeap, address) == B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
// or maybe it was a huge allocation using an area
|
// or maybe it was a huge allocation using an area
|
||||||
area_info areaInfo;
|
area_info areaInfo;
|
||||||
area_id area = area_for(address);
|
area_id area = area_for(address);
|
||||||
|
|||||||
@@ -213,19 +213,17 @@ memalign(size_t alignment, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void*
|
void *
|
||||||
memalign_nogrow(size_t alignment, size_t size)
|
memalign_etc(size_t alignment, size_t size, uint32 flags)
|
||||||
{
|
{
|
||||||
return block_alloc(size, alignment,
|
return block_alloc(size, alignment, flags & CACHE_ALLOC_FLAGS);
|
||||||
CACHE_DONT_WAIT_FOR_MEMORY | CACHE_DONT_LOCK_KERNEL_SPACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void*
|
void
|
||||||
malloc_nogrow(size_t size)
|
free_etc(void *address, uint32 flags)
|
||||||
{
|
{
|
||||||
return block_alloc(size, 0,
|
block_free(address, flags & CACHE_ALLOC_FLAGS);
|
||||||
CACHE_DONT_WAIT_FOR_MEMORY | CACHE_DONT_LOCK_KERNEL_SPACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -192,8 +192,10 @@ VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel,
|
|||||||
VMAddressSpace** _addressSpace)
|
VMAddressSpace** _addressSpace)
|
||||||
{
|
{
|
||||||
VMAddressSpace* addressSpace = kernel
|
VMAddressSpace* addressSpace = kernel
|
||||||
? (VMAddressSpace*)new(nogrow) VMKernelAddressSpace(teamID, base, size)
|
? (VMAddressSpace*)new(std::nothrow) VMKernelAddressSpace(teamID, base,
|
||||||
: (VMAddressSpace*)new(nogrow) VMUserAddressSpace(teamID, base, size);
|
size)
|
||||||
|
: (VMAddressSpace*)new(std::nothrow) VMUserAddressSpace(teamID, base,
|
||||||
|
size);
|
||||||
if (addressSpace == NULL)
|
if (addressSpace == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
|||||||
@@ -409,11 +409,6 @@ public:
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* address, size_t size)
|
|
||||||
{
|
|
||||||
io_request_free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VMAnonymousCache* fCache;
|
VMAnonymousCache* fCache;
|
||||||
page_num_t fPageIndex;
|
page_num_t fPageIndex;
|
||||||
@@ -447,13 +442,13 @@ VMAnonymousCache::~VMAnonymousCache()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMAnonymousCache::Init(bool canOvercommit, int32 numPrecommittedPages,
|
VMAnonymousCache::Init(bool canOvercommit, int32 numPrecommittedPages,
|
||||||
int32 numGuardPages)
|
int32 numGuardPages, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("%p->VMAnonymousCache::Init(canOvercommit = %s, "
|
TRACE("%p->VMAnonymousCache::Init(canOvercommit = %s, "
|
||||||
"numPrecommittedPages = %ld, numGuardPages = %ld)\n", this,
|
"numPrecommittedPages = %ld, numGuardPages = %ld)\n", this,
|
||||||
canOvercommit ? "yes" : "no", numPrecommittedPages, numGuardPages);
|
canOvercommit ? "yes" : "no", numPrecommittedPages, numGuardPages);
|
||||||
|
|
||||||
status_t error = VMCache::Init(CACHE_TYPE_RAM);
|
status_t error = VMCache::Init(CACHE_TYPE_RAM, allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -647,7 +642,7 @@ VMAnonymousCache::WriteAsync(off_t offset, const iovec* vecs, size_t count,
|
|||||||
|
|
||||||
// create our callback
|
// create our callback
|
||||||
WriteCallback* callback = (flags & B_VIP_IO_REQUEST) != 0
|
WriteCallback* callback = (flags & B_VIP_IO_REQUEST) != 0
|
||||||
? new(vip_io_alloc) WriteCallback(this, _callback)
|
? new(malloc_flags(HEAP_PRIORITY_VIP)) WriteCallback(this, _callback)
|
||||||
: new(std::nothrow) WriteCallback(this, _callback);
|
: new(std::nothrow) WriteCallback(this, _callback);
|
||||||
if (callback == NULL) {
|
if (callback == NULL) {
|
||||||
if (newSlot) {
|
if (newSlot) {
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ public:
|
|||||||
|
|
||||||
status_t Init(bool canOvercommit,
|
status_t Init(bool canOvercommit,
|
||||||
int32 numPrecommittedPages,
|
int32 numPrecommittedPages,
|
||||||
int32 numGuardPages);
|
int32 numGuardPages,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual status_t Commit(off_t size, int priority);
|
virtual status_t Commit(off_t size, int priority);
|
||||||
virtual bool HasPage(off_t offset);
|
virtual bool HasPage(off_t offset);
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ VMAnonymousNoSwapCache::~VMAnonymousNoSwapCache()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMAnonymousNoSwapCache::Init(bool canOvercommit, int32 numPrecommittedPages,
|
VMAnonymousNoSwapCache::Init(bool canOvercommit, int32 numPrecommittedPages,
|
||||||
int32 numGuardPages)
|
int32 numGuardPages, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE(("VMAnonymousNoSwapCache::Init(canOvercommit = %s, numGuardPages = %ld) "
|
TRACE(("VMAnonymousNoSwapCache::Init(canOvercommit = %s, numGuardPages = %ld) "
|
||||||
"at %p\n", canOvercommit ? "yes" : "no", numGuardPages, store));
|
"at %p\n", canOvercommit ? "yes" : "no", numGuardPages, store));
|
||||||
|
|
||||||
status_t error = VMCache::Init(CACHE_TYPE_RAM);
|
status_t error = VMCache::Init(CACHE_TYPE_RAM, allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
virtual ~VMAnonymousNoSwapCache();
|
virtual ~VMAnonymousNoSwapCache();
|
||||||
|
|
||||||
status_t Init(bool canOvercommit, int32 numPrecommittedPages,
|
status_t Init(bool canOvercommit, int32 numPrecommittedPages,
|
||||||
int32 numGuardPages);
|
int32 numGuardPages, uint32 allocationFlags);
|
||||||
|
|
||||||
virtual status_t Commit(off_t size, int priority);
|
virtual status_t Commit(off_t size, int priority);
|
||||||
virtual bool HasPage(off_t offset);
|
virtual bool HasPage(off_t offset);
|
||||||
|
|||||||
@@ -47,13 +47,17 @@ VMArea::VMArea(VMAddressSpace* addressSpace, uint32 wiring, uint32 protection)
|
|||||||
|
|
||||||
VMArea::~VMArea()
|
VMArea::~VMArea()
|
||||||
{
|
{
|
||||||
free(page_protections);
|
const uint32 flags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
free(name);
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
// TODO: This might be stricter than necessary.
|
||||||
|
|
||||||
|
free_etc(page_protections, flags);
|
||||||
|
free_etc(name, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMArea::Init(const char* name)
|
VMArea::Init(const char* name, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
// restrict the area name to B_OS_NAME_LENGTH
|
// restrict the area name to B_OS_NAME_LENGTH
|
||||||
size_t length = strlen(name) + 1;
|
size_t length = strlen(name) + 1;
|
||||||
@@ -61,7 +65,7 @@ VMArea::Init(const char* name)
|
|||||||
length = B_OS_NAME_LENGTH;
|
length = B_OS_NAME_LENGTH;
|
||||||
|
|
||||||
// clone the name
|
// clone the name
|
||||||
this->name = (char*)malloc_nogrow(length);
|
this->name = (char*)malloc_etc(length, allocationFlags);
|
||||||
if (this->name == NULL)
|
if (this->name == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
strlcpy(this->name, name, length);
|
strlcpy(this->name, name, length);
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ VMCache::~VMCache()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMCache::Init(uint32 cacheType)
|
VMCache::Init(uint32 cacheType, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "VMCache");
|
mutex_init(&fLock, "VMCache");
|
||||||
VMCache dummyCache;
|
VMCache dummyCache;
|
||||||
@@ -600,7 +600,7 @@ VMCache::Init(uint32 cacheType)
|
|||||||
// initialize in case the following fails
|
// initialize in case the following fails
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fCacheRef = new(nogrow) VMCacheRef(this);
|
fCacheRef = new(malloc_flags(allocationFlags)) VMCacheRef(this);
|
||||||
if (fCacheRef == NULL)
|
if (fCacheRef == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -1346,15 +1346,20 @@ VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
|
|||||||
int32 numPrecommittedPages, int32 numGuardPages, bool swappable,
|
int32 numPrecommittedPages, int32 numGuardPages, bool swappable,
|
||||||
int priority)
|
int priority)
|
||||||
{
|
{
|
||||||
|
uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
if (priority >= VM_PRIORITY_VIP)
|
||||||
|
allocationFlags |= HEAP_PRIORITY_VIP;
|
||||||
|
|
||||||
#if ENABLE_SWAP_SUPPORT
|
#if ENABLE_SWAP_SUPPORT
|
||||||
if (swappable) {
|
if (swappable) {
|
||||||
// TODO: Respect priority!
|
VMAnonymousCache* cache
|
||||||
VMAnonymousCache* cache = new(nogrow) VMAnonymousCache;
|
= new(malloc_flags(allocationFlags)) VMAnonymousCache;
|
||||||
if (cache == NULL)
|
if (cache == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = cache->Init(canOvercommit, numPrecommittedPages,
|
status_t error = cache->Init(canOvercommit, numPrecommittedPages,
|
||||||
numGuardPages);
|
numGuardPages, allocationFlags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
cache->Delete();
|
cache->Delete();
|
||||||
return error;
|
return error;
|
||||||
@@ -1367,12 +1372,13 @@ VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VMAnonymousNoSwapCache* cache = new(nogrow) VMAnonymousNoSwapCache;
|
VMAnonymousNoSwapCache* cache
|
||||||
|
= new(malloc_flags(allocationFlags)) VMAnonymousNoSwapCache;
|
||||||
if (cache == NULL)
|
if (cache == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = cache->Init(canOvercommit, numPrecommittedPages,
|
status_t error = cache->Init(canOvercommit, numPrecommittedPages,
|
||||||
numGuardPages);
|
numGuardPages, allocationFlags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
cache->Delete();
|
cache->Delete();
|
||||||
return error;
|
return error;
|
||||||
@@ -1388,11 +1394,15 @@ VMCacheFactory::CreateAnonymousCache(VMCache*& _cache, bool canOvercommit,
|
|||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
VMCacheFactory::CreateVnodeCache(VMCache*& _cache, struct vnode* vnode)
|
VMCacheFactory::CreateVnodeCache(VMCache*& _cache, struct vnode* vnode)
|
||||||
{
|
{
|
||||||
VMVnodeCache* cache = new(nogrow) VMVnodeCache;
|
const uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
// Note: Vnode cache creation is never VIP.
|
||||||
|
|
||||||
|
VMVnodeCache* cache = new(malloc_flags(allocationFlags)) VMVnodeCache;
|
||||||
if (cache == NULL)
|
if (cache == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = cache->Init(vnode);
|
status_t error = cache->Init(vnode, allocationFlags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
cache->Delete();
|
cache->Delete();
|
||||||
return error;
|
return error;
|
||||||
@@ -1408,11 +1418,15 @@ VMCacheFactory::CreateVnodeCache(VMCache*& _cache, struct vnode* vnode)
|
|||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
VMCacheFactory::CreateDeviceCache(VMCache*& _cache, addr_t baseAddress)
|
VMCacheFactory::CreateDeviceCache(VMCache*& _cache, addr_t baseAddress)
|
||||||
{
|
{
|
||||||
VMDeviceCache* cache = new(nogrow) VMDeviceCache;
|
const uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
// Note: Device cache creation is never VIP.
|
||||||
|
|
||||||
|
VMDeviceCache* cache = new(malloc_flags(allocationFlags)) VMDeviceCache;
|
||||||
if (cache == NULL)
|
if (cache == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = cache->Init(baseAddress);
|
status_t error = cache->Init(baseAddress, allocationFlags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
cache->Delete();
|
cache->Delete();
|
||||||
return error;
|
return error;
|
||||||
@@ -1428,12 +1442,16 @@ VMCacheFactory::CreateDeviceCache(VMCache*& _cache, addr_t baseAddress)
|
|||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
VMCacheFactory::CreateNullCache(int priority, VMCache*& _cache)
|
VMCacheFactory::CreateNullCache(int priority, VMCache*& _cache)
|
||||||
{
|
{
|
||||||
// TODO: Respect priority!
|
uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
VMNullCache* cache = new(nogrow) VMNullCache;
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
if (priority >= VM_PRIORITY_VIP)
|
||||||
|
allocationFlags |= HEAP_PRIORITY_VIP;
|
||||||
|
|
||||||
|
VMNullCache* cache = new(malloc_flags(allocationFlags)) VMNullCache;
|
||||||
if (cache == NULL)
|
if (cache == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = cache->Init();
|
status_t error = cache->Init(allocationFlags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
cache->Delete();
|
cache->Delete();
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMDeviceCache::Init(addr_t baseAddress)
|
VMDeviceCache::Init(addr_t baseAddress, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
fBaseAddress = baseAddress;
|
fBaseAddress = baseAddress;
|
||||||
return VMCache::Init(CACHE_TYPE_DEVICE);
|
return VMCache::Init(CACHE_TYPE_DEVICE, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
class VMDeviceCache : public VMCache {
|
class VMDeviceCache : public VMCache {
|
||||||
public:
|
public:
|
||||||
status_t Init(addr_t baseAddress);
|
status_t Init(addr_t baseAddress, uint32 allocationFlags);
|
||||||
|
|
||||||
virtual bool HasPage(off_t offset);
|
virtual bool HasPage(off_t offset);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -86,11 +86,11 @@ VMKernelAddressSpace::InitObject()
|
|||||||
// create the free lists
|
// create the free lists
|
||||||
size_t size = fEndAddress - fBase + 1;
|
size_t size = fEndAddress - fBase + 1;
|
||||||
fFreeListCount = ld(size) - PAGE_SHIFT + 1;
|
fFreeListCount = ld(size) - PAGE_SHIFT + 1;
|
||||||
fFreeLists = new(nogrow) RangeFreeList[fFreeListCount];
|
fFreeLists = new(std::nothrow) RangeFreeList[fFreeListCount];
|
||||||
if (fFreeLists == NULL)
|
if (fFreeLists == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
Range* range = new(nogrow) Range(fBase, size, Range::RANGE_FREE);
|
Range* range = new(std::nothrow) Range(fBase, size, Range::RANGE_FREE);
|
||||||
if (range == NULL)
|
if (range == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -127,18 +127,21 @@ VMKernelAddressSpace::NextArea(VMArea* _area) const
|
|||||||
|
|
||||||
VMArea*
|
VMArea*
|
||||||
VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring,
|
VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring,
|
||||||
uint32 protection)
|
uint32 protection, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
return VMKernelArea::Create(this, name, wiring, protection);
|
return VMKernelArea::Create(this, name, wiring, protection,
|
||||||
|
allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMKernelAddressSpace::DeleteArea(VMArea* area)
|
VMKernelAddressSpace::DeleteArea(VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", area);
|
TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", area);
|
||||||
|
|
||||||
delete static_cast<VMKernelArea*>(area);
|
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||||
|
area->~VMKernelArea();
|
||||||
|
free_etc(area, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -162,7 +165,7 @@ VMKernelAddressSpace::LookupArea(addr_t address) const
|
|||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||||
size_t size, VMArea* _area)
|
size_t size, VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::InsertArea(%p, %" B_PRIu32 ", %#" B_PRIxSIZE
|
TRACE("VMKernelAddressSpace::InsertArea(%p, %" B_PRIu32 ", %#" B_PRIxSIZE
|
||||||
", %p \"%s\")\n", *_address, addressSpec, size, _area, _area->name);
|
", %p \"%s\")\n", *_address, addressSpec, size, _area, _area->name);
|
||||||
@@ -171,7 +174,7 @@ VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
Range* range;
|
Range* range;
|
||||||
status_t error = _AllocateRange((addr_t)*_address, addressSpec, size,
|
status_t error = _AllocateRange((addr_t)*_address, addressSpec, size,
|
||||||
addressSpec == B_EXACT_ADDRESS, range);
|
addressSpec == B_EXACT_ADDRESS, allocationFlags, range);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -192,13 +195,13 @@ VMKernelAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
//! You must hold the address space's write lock.
|
//! You must hold the address space's write lock.
|
||||||
void
|
void
|
||||||
VMKernelAddressSpace::RemoveArea(VMArea* _area)
|
VMKernelAddressSpace::RemoveArea(VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::RemoveArea(%p)\n", _area);
|
TRACE("VMKernelAddressSpace::RemoveArea(%p)\n", _area);
|
||||||
|
|
||||||
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
VMKernelArea* area = static_cast<VMKernelArea*>(_area);
|
||||||
|
|
||||||
_FreeRange(area->Range());
|
_FreeRange(area->Range(), allocationFlags);
|
||||||
|
|
||||||
fFreeSpace += area->Size();
|
fFreeSpace += area->Size();
|
||||||
|
|
||||||
@@ -230,7 +233,8 @@ VMKernelAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::ResizeArea(%p, %#" B_PRIxSIZE ")\n", _area,
|
TRACE("VMKernelAddressSpace::ResizeArea(%p, %#" B_PRIxSIZE ")\n", _area,
|
||||||
newSize);
|
newSize);
|
||||||
@@ -253,8 +257,9 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
|||||||
} else {
|
} else {
|
||||||
// no free range following -- we need to allocate a new one and
|
// no free range following -- we need to allocate a new one and
|
||||||
// insert it
|
// insert it
|
||||||
nextRange = new(nogrow) Range(range->base + newSize,
|
nextRange = new(malloc_flags(allocationFlags)) Range(
|
||||||
range->size - newSize, Range::RANGE_FREE);
|
range->base + newSize, range->size - newSize,
|
||||||
|
Range::RANGE_FREE);
|
||||||
if (nextRange == NULL)
|
if (nextRange == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
_InsertRange(nextRange);
|
_InsertRange(nextRange);
|
||||||
@@ -274,7 +279,7 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
|||||||
if (sizeDiff == nextRange->size) {
|
if (sizeDiff == nextRange->size) {
|
||||||
// The next range is completely covered -- remove and delete it.
|
// The next range is completely covered -- remove and delete it.
|
||||||
_RemoveRange(nextRange);
|
_RemoveRange(nextRange);
|
||||||
delete nextRange;
|
free_etc(nextRange, allocationFlags);
|
||||||
} else {
|
} else {
|
||||||
// The next range is only partially covered -- shrink it.
|
// The next range is only partially covered -- shrink it.
|
||||||
if (nextRange->type == Range::RANGE_FREE)
|
if (nextRange->type == Range::RANGE_FREE)
|
||||||
@@ -296,7 +301,8 @@ VMKernelAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize)
|
VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::ShrinkAreaHead(%p, %#" B_PRIxSIZE ")\n", _area,
|
TRACE("VMKernelAddressSpace::ShrinkAreaHead(%p, %#" B_PRIxSIZE ")\n", _area,
|
||||||
newSize);
|
newSize);
|
||||||
@@ -323,8 +329,8 @@ VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize)
|
|||||||
} else {
|
} else {
|
||||||
// no free range before -- we need to allocate a new one and
|
// no free range before -- we need to allocate a new one and
|
||||||
// insert it
|
// insert it
|
||||||
previousRange = new(nogrow) Range(range->base, sizeDiff,
|
previousRange = new(malloc_flags(allocationFlags)) Range(range->base,
|
||||||
Range::RANGE_FREE);
|
sizeDiff, Range::RANGE_FREE);
|
||||||
if (previousRange == NULL)
|
if (previousRange == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
range->base += sizeDiff;
|
range->base += sizeDiff;
|
||||||
@@ -342,15 +348,16 @@ VMKernelAddressSpace::ShrinkAreaHead(VMArea* _area, size_t newSize)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::ShrinkAreaTail(VMArea* area, size_t newSize)
|
VMKernelAddressSpace::ShrinkAreaTail(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
return ResizeArea(area, newSize);
|
return ResizeArea(area, newSize, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
VMKernelAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||||
size_t size, uint32 flags)
|
size_t size, uint32 flags, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::ReserveAddressRange(%p, %" B_PRIu32 ", %#"
|
TRACE("VMKernelAddressSpace::ReserveAddressRange(%p, %" B_PRIu32 ", %#"
|
||||||
B_PRIxSIZE ", %#" B_PRIx32 ")\n", *_address, addressSpec, size, flags);
|
B_PRIxSIZE ", %#" B_PRIx32 ")\n", *_address, addressSpec, size, flags);
|
||||||
@@ -362,7 +369,7 @@ VMKernelAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
Range* range;
|
Range* range;
|
||||||
status_t error = _AllocateRange((addr_t)*_address, addressSpec, size, false,
|
status_t error = _AllocateRange((addr_t)*_address, addressSpec, size, false,
|
||||||
range);
|
allocationFlags, range);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -379,7 +386,8 @@ VMKernelAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE("VMKernelAddressSpace::UnreserveAddressRange(%#" B_PRIxADDR ", %#"
|
TRACE("VMKernelAddressSpace::UnreserveAddressRange(%#" B_PRIxADDR ", %#"
|
||||||
B_PRIxSIZE ")\n", address, size);
|
B_PRIxSIZE ")\n", address, size);
|
||||||
@@ -401,7 +409,7 @@ VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
|||||||
nextRange = fRangeList.GetNext(nextRange);
|
nextRange = fRangeList.GetNext(nextRange);
|
||||||
|
|
||||||
if (range->type == Range::RANGE_RESERVED) {
|
if (range->type == Range::RANGE_RESERVED) {
|
||||||
_FreeRange(range);
|
_FreeRange(range, allocationFlags);
|
||||||
Put();
|
Put();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +422,7 @@ VMKernelAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMKernelAddressSpace::UnreserveAllAddressRanges()
|
VMKernelAddressSpace::UnreserveAllAddressRanges(uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
Range* range = fRangeList.Head();
|
Range* range = fRangeList.Head();
|
||||||
while (range != NULL) {
|
while (range != NULL) {
|
||||||
@@ -426,7 +434,7 @@ VMKernelAddressSpace::UnreserveAllAddressRanges()
|
|||||||
nextRange = fRangeList.GetNext(nextRange);
|
nextRange = fRangeList.GetNext(nextRange);
|
||||||
|
|
||||||
if (range->type == Range::RANGE_RESERVED) {
|
if (range->type == Range::RANGE_RESERVED) {
|
||||||
_FreeRange(range);
|
_FreeRange(range, allocationFlags);
|
||||||
Put();
|
Put();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +530,8 @@ VMKernelAddressSpace::_RemoveRange(Range* range)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMKernelAddressSpace::_AllocateRange(addr_t address, uint32 addressSpec,
|
VMKernelAddressSpace::_AllocateRange(addr_t address, uint32 addressSpec,
|
||||||
size_t size, bool allowReservedRange, Range*& _range)
|
size_t size, bool allowReservedRange, uint32 allocationFlags,
|
||||||
|
Range*& _range)
|
||||||
{
|
{
|
||||||
TRACE(" VMKernelAddressSpace::_AllocateRange(address: %#" B_PRIxADDR
|
TRACE(" VMKernelAddressSpace::_AllocateRange(address: %#" B_PRIxADDR
|
||||||
", size: %#" B_PRIxSIZE ", addressSpec: %#" B_PRIx32 ", reserved "
|
", size: %#" B_PRIxSIZE ", addressSpec: %#" B_PRIx32 ", reserved "
|
||||||
@@ -582,8 +591,8 @@ VMKernelAddressSpace::_AllocateRange(addr_t address, uint32 addressSpec,
|
|||||||
// allocation at the beginning of the range
|
// allocation at the beginning of the range
|
||||||
if (range->size > size) {
|
if (range->size > size) {
|
||||||
// only partial -- split the range
|
// only partial -- split the range
|
||||||
Range* leftOverRange = new(nogrow) Range(address + size,
|
Range* leftOverRange = new(malloc_flags(allocationFlags)) Range(
|
||||||
range->size - size, range);
|
address + size, range->size - size, range);
|
||||||
if (leftOverRange == NULL)
|
if (leftOverRange == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -592,8 +601,8 @@ VMKernelAddressSpace::_AllocateRange(addr_t address, uint32 addressSpec,
|
|||||||
}
|
}
|
||||||
} else if (address + size == range->base + range->size) {
|
} else if (address + size == range->base + range->size) {
|
||||||
// allocation at the end of the range -- split the range
|
// allocation at the end of the range -- split the range
|
||||||
Range* leftOverRange = new(nogrow) Range(range->base,
|
Range* leftOverRange = new(malloc_flags(allocationFlags)) Range(
|
||||||
range->size - size, range);
|
range->base, range->size - size, range);
|
||||||
if (leftOverRange == NULL)
|
if (leftOverRange == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -602,14 +611,14 @@ VMKernelAddressSpace::_AllocateRange(addr_t address, uint32 addressSpec,
|
|||||||
_InsertRange(leftOverRange);
|
_InsertRange(leftOverRange);
|
||||||
} else {
|
} else {
|
||||||
// allocation in the middle of the range -- split the range in three
|
// allocation in the middle of the range -- split the range in three
|
||||||
Range* leftOverRange1 = new(nogrow) Range(range->base,
|
Range* leftOverRange1 = new(malloc_flags(allocationFlags)) Range(
|
||||||
address - range->base, range);
|
range->base, address - range->base, range);
|
||||||
if (leftOverRange1 == NULL)
|
if (leftOverRange1 == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Range* leftOverRange2 = new(nogrow) Range(address + size,
|
Range* leftOverRange2 = new(malloc_flags(allocationFlags)) Range(
|
||||||
range->size - size - leftOverRange1->size, range);
|
address + size, range->size - size - leftOverRange1->size, range);
|
||||||
if (leftOverRange2 == NULL) {
|
if (leftOverRange2 == NULL) {
|
||||||
delete leftOverRange1;
|
free_etc(leftOverRange1, allocationFlags);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,7 +761,7 @@ TRACE(" -> reserved range not allowed\n");
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMKernelAddressSpace::_FreeRange(Range* range)
|
VMKernelAddressSpace::_FreeRange(Range* range, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
TRACE(" VMKernelAddressSpace::_FreeRange(%p (%#" B_PRIxADDR ", %#"
|
TRACE(" VMKernelAddressSpace::_FreeRange(%p (%#" B_PRIxADDR ", %#"
|
||||||
B_PRIxSIZE ", %d))\n", range, range->base, range->size, range->type);
|
B_PRIxSIZE ", %d))\n", range, range->base, range->size, range->type);
|
||||||
@@ -769,15 +778,15 @@ VMKernelAddressSpace::_FreeRange(Range* range)
|
|||||||
_RemoveRange(range);
|
_RemoveRange(range);
|
||||||
_RemoveRange(nextRange);
|
_RemoveRange(nextRange);
|
||||||
previousRange->size += range->size + nextRange->size;
|
previousRange->size += range->size + nextRange->size;
|
||||||
delete range;
|
free_etc(range, allocationFlags);
|
||||||
delete nextRange;
|
free_etc(nextRange, allocationFlags);
|
||||||
_FreeListInsertRange(previousRange, previousRange->size);
|
_FreeListInsertRange(previousRange, previousRange->size);
|
||||||
} else {
|
} else {
|
||||||
// join with the previous range only, delete the supplied one
|
// join with the previous range only, delete the supplied one
|
||||||
_FreeListRemoveRange(previousRange, previousRange->size);
|
_FreeListRemoveRange(previousRange, previousRange->size);
|
||||||
_RemoveRange(range);
|
_RemoveRange(range);
|
||||||
previousRange->size += range->size;
|
previousRange->size += range->size;
|
||||||
delete range;
|
free_etc(range, allocationFlags);
|
||||||
_FreeListInsertRange(previousRange, previousRange->size);
|
_FreeListInsertRange(previousRange, previousRange->size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -785,7 +794,7 @@ VMKernelAddressSpace::_FreeRange(Range* range)
|
|||||||
// join with the next range and delete it
|
// join with the next range and delete it
|
||||||
_RemoveRange(nextRange);
|
_RemoveRange(nextRange);
|
||||||
range->size += nextRange->size;
|
range->size += nextRange->size;
|
||||||
delete nextRange;
|
free_etc(nextRange, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark the range free and add it to the respective free list
|
// mark the range free and add it to the respective free list
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef VM_KERNEL_ADDRESS_SPACE_H
|
#ifndef VM_KERNEL_ADDRESS_SPACE_H
|
||||||
@@ -24,23 +24,30 @@ public:
|
|||||||
|
|
||||||
virtual VMArea* LookupArea(addr_t address) const;
|
virtual VMArea* LookupArea(addr_t address) const;
|
||||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||||
uint32 protection);
|
uint32 protection, uint32 allocationFlags);
|
||||||
virtual void DeleteArea(VMArea* area);
|
virtual void DeleteArea(VMArea* area,
|
||||||
|
uint32 allocationFlags);
|
||||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||||
size_t size, VMArea* area);
|
size_t size, VMArea* area,
|
||||||
virtual void RemoveArea(VMArea* area);
|
uint32 allocationFlags);
|
||||||
|
virtual void RemoveArea(VMArea* area,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
||||||
virtual status_t ResizeArea(VMArea* area, size_t newSize);
|
virtual status_t ResizeArea(VMArea* area, size_t newSize,
|
||||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize);
|
uint32 allocationFlags);
|
||||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize);
|
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual status_t ReserveAddressRange(void** _address,
|
virtual status_t ReserveAddressRange(void** _address,
|
||||||
uint32 addressSpec, size_t size,
|
uint32 addressSpec, size_t size,
|
||||||
uint32 flags);
|
uint32 flags, uint32 allocationFlags);
|
||||||
virtual status_t UnreserveAddressRange(addr_t address,
|
virtual status_t UnreserveAddressRange(addr_t address,
|
||||||
size_t size);
|
size_t size, uint32 allocationFlags);
|
||||||
virtual void UnreserveAllAddressRanges();
|
virtual void UnreserveAllAddressRanges(
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual void Dump() const;
|
virtual void Dump() const;
|
||||||
|
|
||||||
@@ -62,12 +69,14 @@ private:
|
|||||||
|
|
||||||
status_t _AllocateRange(addr_t address,
|
status_t _AllocateRange(addr_t address,
|
||||||
uint32 addressSpec, size_t size,
|
uint32 addressSpec, size_t size,
|
||||||
bool allowReservedRange, Range*& _range);
|
bool allowReservedRange,
|
||||||
|
uint32 allocationFlags, Range*& _range);
|
||||||
Range* _FindFreeRange(addr_t start, size_t size,
|
Range* _FindFreeRange(addr_t start, size_t size,
|
||||||
size_t alignment, uint32 addressSpec,
|
size_t alignment, uint32 addressSpec,
|
||||||
bool allowReservedRange,
|
bool allowReservedRange,
|
||||||
addr_t& _foundAddress);
|
addr_t& _foundAddress);
|
||||||
void _FreeRange(Range* range);
|
void _FreeRange(Range* range,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
void _CheckStructures() const;
|
void _CheckStructures() const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -25,14 +25,14 @@ VMKernelArea::~VMKernelArea()
|
|||||||
|
|
||||||
/*static*/ VMKernelArea*
|
/*static*/ VMKernelArea*
|
||||||
VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name,
|
VMKernelArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||||
uint32 wiring, uint32 protection)
|
uint32 wiring, uint32 protection, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMKernelArea* area = new(nogrow) VMKernelArea(addressSpace, wiring,
|
VMKernelArea* area = new(malloc_flags(allocationFlags)) VMKernelArea(
|
||||||
protection);
|
addressSpace, wiring, protection);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (area->Init(name) != B_OK) {
|
if (area->Init(name, allocationFlags) != B_OK) {
|
||||||
delete area;
|
delete area;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
#ifndef VM_KERNEL_AREA_H
|
#ifndef VM_KERNEL_AREA_H
|
||||||
@@ -115,7 +115,7 @@ struct VMKernelArea : VMArea, AVLTreeNode {
|
|||||||
|
|
||||||
static VMKernelArea* Create(VMAddressSpace* addressSpace,
|
static VMKernelArea* Create(VMAddressSpace* addressSpace,
|
||||||
const char* name, uint32 wiring,
|
const char* name, uint32 wiring,
|
||||||
uint32 protection);
|
uint32 protection, uint32 allocationFlags);
|
||||||
|
|
||||||
VMKernelAddressRange* Range() const
|
VMKernelAddressRange* Range() const
|
||||||
{ return fRange; }
|
{ return fRange; }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMNullCache::Init()
|
VMNullCache::Init(uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
return VMCache::Init(CACHE_TYPE_NULL);
|
return VMCache::Init(CACHE_TYPE_NULL, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
class VMNullCache : public VMCache {
|
class VMNullCache : public VMCache {
|
||||||
public:
|
public:
|
||||||
status_t Init();
|
status_t Init(uint32 allocationFlags);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -75,16 +75,18 @@ VMUserAddressSpace::NextArea(VMArea* _area) const
|
|||||||
|
|
||||||
VMArea*
|
VMArea*
|
||||||
VMUserAddressSpace::CreateArea(const char* name, uint32 wiring,
|
VMUserAddressSpace::CreateArea(const char* name, uint32 wiring,
|
||||||
uint32 protection)
|
uint32 protection, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
return VMUserArea::Create(this, name, wiring, protection);
|
return VMUserArea::Create(this, name, wiring, protection, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMUserAddressSpace::DeleteArea(VMArea* area)
|
VMUserAddressSpace::DeleteArea(VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
delete static_cast<VMUserArea*>(area);
|
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||||
|
area->~VMUserArea();
|
||||||
|
free_etc(area, allocationFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -118,7 +120,7 @@ VMUserAddressSpace::LookupArea(addr_t address) const
|
|||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
||||||
size_t size, VMArea* _area)
|
size_t size, VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||||
|
|
||||||
@@ -151,7 +153,8 @@ VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _InsertAreaSlot(searchBase, size, searchEnd, addressSpec, area);
|
status = _InsertAreaSlot(searchBase, size, searchEnd, addressSpec, area,
|
||||||
|
allocationFlags);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
*_address = (void*)area->Base();
|
*_address = (void*)area->Base();
|
||||||
fFreeSpace -= area->Size();
|
fFreeSpace -= area->Size();
|
||||||
@@ -163,7 +166,7 @@ VMUserAddressSpace::InsertArea(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
//! You must hold the address space's write lock.
|
//! You must hold the address space's write lock.
|
||||||
void
|
void
|
||||||
VMUserAddressSpace::RemoveArea(VMArea* _area)
|
VMUserAddressSpace::RemoveArea(VMArea* _area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||||
|
|
||||||
@@ -206,7 +209,8 @@ VMUserAddressSpace::CanResizeArea(VMArea* area, size_t newSize)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
VMUserArea* area = static_cast<VMUserArea*>(_area);
|
||||||
|
|
||||||
@@ -224,10 +228,12 @@ VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
|||||||
// resize reserved area
|
// resize reserved area
|
||||||
addr_t offset = area->Base() + newSize - next->Base();
|
addr_t offset = area->Base() + newSize - next->Base();
|
||||||
if (next->Size() <= offset) {
|
if (next->Size() <= offset) {
|
||||||
RemoveArea(next);
|
RemoveArea(next, allocationFlags);
|
||||||
delete next;
|
next->~VMUserArea();
|
||||||
|
free_etc(next, allocationFlags);
|
||||||
} else {
|
} else {
|
||||||
status_t error = ShrinkAreaHead(next, next->Size() - offset);
|
status_t error = ShrinkAreaHead(next, next->Size() - offset,
|
||||||
|
allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -239,7 +245,8 @@ VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::ShrinkAreaHead(VMArea* area, size_t size)
|
VMUserAddressSpace::ShrinkAreaHead(VMArea* area, size_t size,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
size_t oldSize = area->Size();
|
size_t oldSize = area->Size();
|
||||||
if (size == oldSize)
|
if (size == oldSize)
|
||||||
@@ -253,7 +260,8 @@ VMUserAddressSpace::ShrinkAreaHead(VMArea* area, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::ShrinkAreaTail(VMArea* area, size_t size)
|
VMUserAddressSpace::ShrinkAreaTail(VMArea* area, size_t size,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
size_t oldSize = area->Size();
|
size_t oldSize = area->Size();
|
||||||
if (size == oldSize)
|
if (size == oldSize)
|
||||||
@@ -267,7 +275,7 @@ VMUserAddressSpace::ShrinkAreaTail(VMArea* area, size_t size)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
||||||
size_t size, uint32 flags)
|
size_t size, uint32 flags, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
// check to see if this address space has entered DELETE state
|
// check to see if this address space has entered DELETE state
|
||||||
if (fDeleting) {
|
if (fDeleting) {
|
||||||
@@ -276,13 +284,15 @@ VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
|||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
VMUserArea* area = VMUserArea::CreateReserved(this, flags);
|
VMUserArea* area = VMUserArea::CreateReserved(this, flags, allocationFlags);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = InsertArea(_address, addressSpec, size, area);
|
status_t status = InsertArea(_address, addressSpec, size, area,
|
||||||
|
allocationFlags);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
delete area;
|
area->~VMUserArea();
|
||||||
|
free_etc(area, allocationFlags);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +305,8 @@ VMUserAddressSpace::ReserveAddressRange(void** _address, uint32 addressSpec,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
// check to see if this address space has entered DELETE state
|
// check to see if this address space has entered DELETE state
|
||||||
if (fDeleting) {
|
if (fDeleting) {
|
||||||
@@ -313,9 +324,10 @@ VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
|||||||
break;
|
break;
|
||||||
if (area->id == RESERVED_AREA_ID && area->Base() >= (addr_t)address) {
|
if (area->id == RESERVED_AREA_ID && area->Base() >= (addr_t)address) {
|
||||||
// remove reserved range
|
// remove reserved range
|
||||||
RemoveArea(area);
|
RemoveArea(area, allocationFlags);
|
||||||
Put();
|
Put();
|
||||||
delete area;
|
area->~VMUserArea();
|
||||||
|
free_etc(area, allocationFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,14 +336,15 @@ VMUserAddressSpace::UnreserveAddressRange(addr_t address, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
VMUserAddressSpace::UnreserveAllAddressRanges()
|
VMUserAddressSpace::UnreserveAllAddressRanges(uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
|
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
|
||||||
VMUserArea* area = it.Next();) {
|
VMUserArea* area = it.Next();) {
|
||||||
if (area->id == RESERVED_AREA_ID) {
|
if (area->id == RESERVED_AREA_ID) {
|
||||||
RemoveArea(area);
|
RemoveArea(area, allocationFlags);
|
||||||
Put();
|
Put();
|
||||||
delete area;
|
area->~VMUserArea();
|
||||||
|
free_etc(area, allocationFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +375,7 @@ VMUserAddressSpace::Dump() const
|
|||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
||||||
VMUserArea* area)
|
VMUserArea* area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* next;
|
VMUserArea* next;
|
||||||
|
|
||||||
@@ -395,7 +408,8 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
|||||||
// the new area fully covers the reversed range
|
// the new area fully covers the reversed range
|
||||||
fAreas.Remove(next);
|
fAreas.Remove(next);
|
||||||
Put();
|
Put();
|
||||||
delete next;
|
next->~VMUserArea();
|
||||||
|
free_etc(next, allocationFlags);
|
||||||
} else {
|
} else {
|
||||||
// resize the reserved range behind the area
|
// resize the reserved range behind the area
|
||||||
next->SetBase(next->Base() + size);
|
next->SetBase(next->Base() + size);
|
||||||
@@ -411,7 +425,7 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
|||||||
// the area splits the reserved range into two separate ones
|
// the area splits the reserved range into two separate ones
|
||||||
// we need a new reserved area to cover this space
|
// we need a new reserved area to cover this space
|
||||||
VMUserArea* reserved = VMUserArea::CreateReserved(this,
|
VMUserArea* reserved = VMUserArea::CreateReserved(this,
|
||||||
next->protection);
|
next->protection, allocationFlags);
|
||||||
if (reserved == NULL)
|
if (reserved == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -437,7 +451,7 @@ VMUserAddressSpace::_InsertAreaIntoReservedRegion(addr_t start, size_t size,
|
|||||||
/*! Must be called with this address space's write lock held */
|
/*! Must be called with this address space's write lock held */
|
||||||
status_t
|
status_t
|
||||||
VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
||||||
uint32 addressSpec, VMUserArea* area)
|
uint32 addressSpec, VMUserArea* area, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* last = NULL;
|
VMUserArea* last = NULL;
|
||||||
VMUserArea* next;
|
VMUserArea* next;
|
||||||
@@ -454,7 +468,8 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
|
|||||||
|
|
||||||
if (addressSpec == B_EXACT_ADDRESS && area->id != RESERVED_AREA_ID) {
|
if (addressSpec == B_EXACT_ADDRESS && area->id != RESERVED_AREA_ID) {
|
||||||
// search for a reserved area
|
// search for a reserved area
|
||||||
status_t status = _InsertAreaIntoReservedRegion(start, size, area);
|
status_t status = _InsertAreaIntoReservedRegion(start, size, area,
|
||||||
|
allocationFlags);
|
||||||
if (status == B_OK || status == B_BAD_VALUE)
|
if (status == B_OK || status == B_BAD_VALUE)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -555,7 +570,8 @@ second_chance:
|
|||||||
|
|
||||||
foundSpot = true;
|
foundSpot = true;
|
||||||
area->SetBase(alignedBase);
|
area->SetBase(alignedBase);
|
||||||
delete next;
|
next->~VMUserArea();
|
||||||
|
free_etc(next, allocationFlags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,32 +22,40 @@ public:
|
|||||||
|
|
||||||
virtual VMArea* LookupArea(addr_t address) const;
|
virtual VMArea* LookupArea(addr_t address) const;
|
||||||
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
virtual VMArea* CreateArea(const char* name, uint32 wiring,
|
||||||
uint32 protection);
|
uint32 protection, uint32 allocationFlags);
|
||||||
virtual void DeleteArea(VMArea* area);
|
virtual void DeleteArea(VMArea* area,
|
||||||
|
uint32 allocationFlags);
|
||||||
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
virtual status_t InsertArea(void** _address, uint32 addressSpec,
|
||||||
size_t size, VMArea* area);
|
size_t size, VMArea* area,
|
||||||
virtual void RemoveArea(VMArea* area);
|
uint32 allocationFlags);
|
||||||
|
virtual void RemoveArea(VMArea* area,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
virtual bool CanResizeArea(VMArea* area, size_t newSize);
|
||||||
virtual status_t ResizeArea(VMArea* area, size_t newSize);
|
virtual status_t ResizeArea(VMArea* area, size_t newSize,
|
||||||
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize);
|
uint32 allocationFlags);
|
||||||
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize);
|
virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize,
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual status_t ReserveAddressRange(void** _address,
|
virtual status_t ReserveAddressRange(void** _address,
|
||||||
uint32 addressSpec, size_t size,
|
uint32 addressSpec, size_t size,
|
||||||
uint32 flags);
|
uint32 flags, uint32 allocationFlags);
|
||||||
virtual status_t UnreserveAddressRange(addr_t address,
|
virtual status_t UnreserveAddressRange(addr_t address,
|
||||||
size_t size);
|
size_t size, uint32 allocationFlags);
|
||||||
virtual void UnreserveAllAddressRanges();
|
virtual void UnreserveAllAddressRanges(
|
||||||
|
uint32 allocationFlags);
|
||||||
|
|
||||||
virtual void Dump() const;
|
virtual void Dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _InsertAreaIntoReservedRegion(addr_t start,
|
status_t _InsertAreaIntoReservedRegion(addr_t start,
|
||||||
size_t size, VMUserArea* area);
|
size_t size, VMUserArea* area,
|
||||||
|
uint32 allocationFlags);
|
||||||
status_t _InsertAreaSlot(addr_t start, addr_t size,
|
status_t _InsertAreaSlot(addr_t start, addr_t size,
|
||||||
addr_t end, uint32 addressSpec,
|
addr_t end, uint32 addressSpec,
|
||||||
VMUserArea* area);
|
VMUserArea* area, uint32 allocationFlags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VMUserAreaList fAreas;
|
VMUserAreaList fAreas;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -25,14 +25,14 @@ VMUserArea::~VMUserArea()
|
|||||||
|
|
||||||
/*static*/ VMUserArea*
|
/*static*/ VMUserArea*
|
||||||
VMUserArea::Create(VMAddressSpace* addressSpace, const char* name,
|
VMUserArea::Create(VMAddressSpace* addressSpace, const char* name,
|
||||||
uint32 wiring, uint32 protection)
|
uint32 wiring, uint32 protection, uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* area = new(nogrow) VMUserArea(addressSpace, wiring,
|
VMUserArea* area = new(malloc_flags(allocationFlags)) VMUserArea(
|
||||||
protection);
|
addressSpace, wiring, protection);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (area->Init(name) != B_OK) {
|
if (area->Init(name, allocationFlags) != B_OK) {
|
||||||
delete area;
|
delete area;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -42,9 +42,11 @@ VMUserArea::Create(VMAddressSpace* addressSpace, const char* name,
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ VMUserArea*
|
/*static*/ VMUserArea*
|
||||||
VMUserArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags)
|
VMUserArea::CreateReserved(VMAddressSpace* addressSpace, uint32 flags,
|
||||||
|
uint32 allocationFlags)
|
||||||
{
|
{
|
||||||
VMUserArea* area = new(nogrow) VMUserArea(addressSpace, 0, 0);
|
VMUserArea* area = new(malloc_flags(allocationFlags)) VMUserArea(
|
||||||
|
addressSpace, 0, 0);
|
||||||
if (area != NULL) {
|
if (area != NULL) {
|
||||||
area->id = RESERVED_AREA_ID;
|
area->id = RESERVED_AREA_ID;
|
||||||
area->protection = flags;
|
area->protection = flags;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
#ifndef VM_USER_AREA_H
|
#ifndef VM_USER_AREA_H
|
||||||
@@ -19,9 +19,9 @@ struct VMUserArea : VMArea {
|
|||||||
|
|
||||||
static VMUserArea* Create(VMAddressSpace* addressSpace,
|
static VMUserArea* Create(VMAddressSpace* addressSpace,
|
||||||
const char* name, uint32 wiring,
|
const char* name, uint32 wiring,
|
||||||
uint32 protection);
|
uint32 protection, uint32 allocationFlags);
|
||||||
static VMUserArea* CreateReserved(VMAddressSpace* addressSpace,
|
static VMUserArea* CreateReserved(VMAddressSpace* addressSpace,
|
||||||
uint32 flags);
|
uint32 flags, uint32 allocationFlags);
|
||||||
|
|
||||||
DoublyLinkedListLink<VMUserArea>& AddressSpaceLink()
|
DoublyLinkedListLink<VMUserArea>& AddressSpaceLink()
|
||||||
{ return fAddressSpaceLink; }
|
{ return fAddressSpaceLink; }
|
||||||
|
|||||||
+63
-28
@@ -565,6 +565,17 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int priority;
|
||||||
|
uint32 allocationFlags;
|
||||||
|
if (addressSpace == VMAddressSpace::Kernel()) {
|
||||||
|
priority = VM_PRIORITY_SYSTEM;
|
||||||
|
allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
} else {
|
||||||
|
priority = VM_PRIORITY_USER;
|
||||||
|
allocationFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
VMCache* cache = vm_area_get_locked_cache(area);
|
VMCache* cache = vm_area_get_locked_cache(area);
|
||||||
VMCacheChainLocker cacheChainLocker(cache);
|
VMCacheChainLocker cacheChainLocker(cache);
|
||||||
cacheChainLocker.LockAllSourceCaches();
|
cacheChainLocker.LockAllSourceCaches();
|
||||||
@@ -574,7 +585,8 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
size_t oldSize = area->Size();
|
size_t oldSize = area->Size();
|
||||||
size_t newSize = address - area->Base();
|
size_t newSize = address - area->Base();
|
||||||
|
|
||||||
status_t error = addressSpace->ShrinkAreaTail(area, newSize);
|
status_t error = addressSpace->ShrinkAreaTail(area, newSize,
|
||||||
|
allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -587,9 +599,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
// Since VMCache::Resize() can temporarily drop the lock, we must
|
// Since VMCache::Resize() can temporarily drop the lock, we must
|
||||||
// unlock all lower caches to prevent locking order inversion.
|
// unlock all lower caches to prevent locking order inversion.
|
||||||
cacheChainLocker.Unlock(cache);
|
cacheChainLocker.Unlock(cache);
|
||||||
cache->Resize(cache->virtual_base + newSize,
|
cache->Resize(cache->virtual_base + newSize, priority);
|
||||||
addressSpace == VMAddressSpace::Kernel()
|
|
||||||
? VM_PRIORITY_SYSTEM : VM_PRIORITY_USER);
|
|
||||||
cache->ReleaseRefAndUnlock();
|
cache->ReleaseRefAndUnlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,7 +616,8 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
unmap_pages(area, oldBase, newBase - oldBase);
|
unmap_pages(area, oldBase, newBase - oldBase);
|
||||||
|
|
||||||
// resize the area
|
// resize the area
|
||||||
status_t error = addressSpace->ShrinkAreaHead(area, newSize);
|
status_t error = addressSpace->ShrinkAreaHead(area, newSize,
|
||||||
|
allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -630,7 +641,8 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
|
|
||||||
// resize the area
|
// resize the area
|
||||||
addr_t oldSize = area->Size();
|
addr_t oldSize = area->Size();
|
||||||
status_t error = addressSpace->ShrinkAreaTail(area, firstNewSize);
|
status_t error = addressSpace->ShrinkAreaTail(area, firstNewSize,
|
||||||
|
allocationFlags);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -646,7 +658,7 @@ cut_area(VMAddressSpace* addressSpace, VMArea* area, addr_t address,
|
|||||||
B_EXACT_ADDRESS, area->wiring, area->protection, REGION_NO_PRIVATE_MAP,
|
B_EXACT_ADDRESS, area->wiring, area->protection, REGION_NO_PRIVATE_MAP,
|
||||||
&secondArea, area->name, 0, kernel);
|
&secondArea, area->name, 0, kernel);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
addressSpace->ShrinkAreaTail(area, oldSize);
|
addressSpace->ShrinkAreaTail(area, oldSize, allocationFlags);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,7 +727,19 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache,
|
|||||||
addressSpec, wiring, protection, _area, areaName));
|
addressSpec, wiring, protection, _area, areaName));
|
||||||
cache->AssertLocked();
|
cache->AssertLocked();
|
||||||
|
|
||||||
VMArea* area = addressSpace->CreateArea(areaName, wiring, protection);
|
uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
int priority;
|
||||||
|
if (addressSpace != VMAddressSpace::Kernel()) {
|
||||||
|
priority = VM_PRIORITY_USER;
|
||||||
|
} else if ((flags & CREATE_AREA_PRIORITY_VIP) != 0) {
|
||||||
|
priority = VM_PRIORITY_VIP;
|
||||||
|
allocationFlags |= HEAP_PRIORITY_VIP;
|
||||||
|
} else
|
||||||
|
priority = VM_PRIORITY_SYSTEM;
|
||||||
|
|
||||||
|
VMArea* area = addressSpace->CreateArea(areaName, wiring, protection,
|
||||||
|
allocationFlags);
|
||||||
if (area == NULL)
|
if (area == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -745,14 +769,6 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache,
|
|||||||
cache = newCache;
|
cache = newCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority;
|
|
||||||
if (addressSpace != VMAddressSpace::Kernel())
|
|
||||||
priority = VM_PRIORITY_USER;
|
|
||||||
else if ((flags & CREATE_AREA_PRIORITY_VIP) != 0)
|
|
||||||
priority = VM_PRIORITY_VIP;
|
|
||||||
else
|
|
||||||
priority = VM_PRIORITY_SYSTEM;
|
|
||||||
|
|
||||||
status = cache->SetMinimalCommitment(size, priority);
|
status = cache->SetMinimalCommitment(size, priority);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err2;
|
goto err2;
|
||||||
@@ -773,7 +789,8 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache,
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = addressSpace->InsertArea(_virtualAddress, addressSpec, size, area);
|
status = addressSpace->InsertArea(_virtualAddress, addressSpec, size, area,
|
||||||
|
allocationFlags);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
// TODO: wait and try again once this is working in the backend
|
// TODO: wait and try again once this is working in the backend
|
||||||
#if 0
|
#if 0
|
||||||
@@ -816,7 +833,7 @@ err2:
|
|||||||
sourceCache->Lock();
|
sourceCache->Lock();
|
||||||
}
|
}
|
||||||
err1:
|
err1:
|
||||||
addressSpace->DeleteArea(area);
|
addressSpace->DeleteArea(area, allocationFlags);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,7 +886,10 @@ vm_unreserve_address_range(team_id team, void* address, addr_t size)
|
|||||||
if (!locker.IsLocked())
|
if (!locker.IsLocked())
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
return locker.AddressSpace()->UnreserveAddressRange((addr_t)address, size);
|
VMAddressSpace* addressSpace = locker.AddressSpace();
|
||||||
|
return addressSpace->UnreserveAddressRange((addr_t)address, size,
|
||||||
|
addressSpace == VMAddressSpace::Kernel()
|
||||||
|
? HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -884,8 +904,11 @@ vm_reserve_address_range(team_id team, void** _address, uint32 addressSpec,
|
|||||||
if (!locker.IsLocked())
|
if (!locker.IsLocked())
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
return locker.AddressSpace()->ReserveAddressRange(_address, addressSpec,
|
VMAddressSpace* addressSpace = locker.AddressSpace();
|
||||||
size, flags);
|
return addressSpace->ReserveAddressRange(_address, addressSpec,
|
||||||
|
size, flags,
|
||||||
|
addressSpace == VMAddressSpace::Kernel()
|
||||||
|
? HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1852,13 +1875,13 @@ delete_area(VMAddressSpace* addressSpace, VMArea* area,
|
|||||||
area->cache->WriteModified();
|
area->cache->WriteModified();
|
||||||
|
|
||||||
arch_vm_unset_memory_type(area);
|
arch_vm_unset_memory_type(area);
|
||||||
addressSpace->RemoveArea(area);
|
addressSpace->RemoveArea(area, 0);
|
||||||
addressSpace->Put();
|
addressSpace->Put();
|
||||||
|
|
||||||
area->cache->RemoveArea(area);
|
area->cache->RemoveArea(area);
|
||||||
area->cache->ReleaseRef();
|
area->cache->ReleaseRef();
|
||||||
|
|
||||||
addressSpace->DeleteArea(area);
|
addressSpace->DeleteArea(area, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2882,7 +2905,7 @@ vm_delete_areas(struct VMAddressSpace* addressSpace, bool deletingAddressSpace)
|
|||||||
addressSpace->WriteLock();
|
addressSpace->WriteLock();
|
||||||
|
|
||||||
// remove all reserved areas in this address space
|
// remove all reserved areas in this address space
|
||||||
addressSpace->UnreserveAllAddressRanges();
|
addressSpace->UnreserveAllAddressRanges(0);
|
||||||
|
|
||||||
// delete all the areas in this address space
|
// delete all the areas in this address space
|
||||||
while (VMArea* area = addressSpace->FirstArea())
|
while (VMArea* area = addressSpace->FirstArea())
|
||||||
@@ -3267,11 +3290,13 @@ vm_init(kernel_args* args)
|
|||||||
|
|
||||||
slab_init(args);
|
slab_init(args);
|
||||||
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
// map in the new heap and initialize it
|
// map in the new heap and initialize it
|
||||||
addr_t heapBase = vm_allocate_early(args, heapSize, heapSize,
|
addr_t heapBase = vm_allocate_early(args, heapSize, heapSize,
|
||||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, false);
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, false);
|
||||||
TRACE(("heap at 0x%lx\n", heapBase));
|
TRACE(("heap at 0x%lx\n", heapBase));
|
||||||
heap_init(heapBase, heapSize);
|
heap_init(heapBase, heapSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialize the free page list and physical page mapper
|
// initialize the free page list and physical page mapper
|
||||||
vm_page_init(args);
|
vm_page_init(args);
|
||||||
@@ -3297,9 +3322,11 @@ vm_init(kernel_args* args)
|
|||||||
|
|
||||||
// allocate areas to represent stuff that already exists
|
// allocate areas to represent stuff that already exists
|
||||||
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
address = (void*)ROUNDDOWN(heapBase, B_PAGE_SIZE);
|
address = (void*)ROUNDDOWN(heapBase, B_PAGE_SIZE);
|
||||||
create_area("kernel heap", &address, B_EXACT_ADDRESS, heapSize,
|
create_area("kernel heap", &address, B_EXACT_ADDRESS, heapSize,
|
||||||
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
#endif
|
||||||
|
|
||||||
allocate_kernel_args(args);
|
allocate_kernel_args(args);
|
||||||
|
|
||||||
@@ -3384,7 +3411,12 @@ vm_init_post_sem(kernel_args* args)
|
|||||||
VMAddressSpace::InitPostSem();
|
VMAddressSpace::InitPostSem();
|
||||||
|
|
||||||
slab_init_post_sem();
|
slab_init_post_sem();
|
||||||
return heap_init_post_sem();
|
|
||||||
|
#if !USE_SLAB_ALLOCATOR_FOR_MALLOC
|
||||||
|
heap_init_post_sem();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4230,6 +4262,8 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
|
|
||||||
int priority = kernel && anyKernelArea
|
int priority = kernel && anyKernelArea
|
||||||
? VM_PRIORITY_SYSTEM : VM_PRIORITY_USER;
|
? VM_PRIORITY_SYSTEM : VM_PRIORITY_USER;
|
||||||
|
uint32 allocationFlags = kernel && anyKernelArea
|
||||||
|
? HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE : 0;
|
||||||
|
|
||||||
if (oldSize < newSize) {
|
if (oldSize < newSize) {
|
||||||
// Growing the cache can fail, so we do it first.
|
// Growing the cache can fail, so we do it first.
|
||||||
@@ -4240,7 +4274,8 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
|
|
||||||
for (VMArea* current = cache->areas; current != NULL;
|
for (VMArea* current = cache->areas; current != NULL;
|
||||||
current = current->cache_next) {
|
current = current->cache_next) {
|
||||||
status = current->address_space->ResizeArea(current, newSize);
|
status = current->address_space->ResizeArea(current, newSize,
|
||||||
|
allocationFlags);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -4266,8 +4301,8 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
// This can fail, too, in which case we're seriously screwed.
|
// This can fail, too, in which case we're seriously screwed.
|
||||||
for (VMArea* current = cache->areas; current != NULL;
|
for (VMArea* current = cache->areas; current != NULL;
|
||||||
current = current->cache_next) {
|
current = current->cache_next) {
|
||||||
if (current->address_space->ResizeArea(current, oldSize)
|
if (current->address_space->ResizeArea(current, oldSize,
|
||||||
!= B_OK) {
|
allocationFlags) != B_OK) {
|
||||||
panic("vm_resize_area(): Failed and not being able to restore "
|
panic("vm_resize_area(): Failed and not being able to restore "
|
||||||
"original state.");
|
"original state.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1731,8 +1731,12 @@ vm_page_write_modified_page_range(struct VMCache* cache, uint32 firstPage,
|
|||||||
if (maxPages < 0 || maxPages > kMaxPages)
|
if (maxPages < 0 || maxPages > kMaxPages)
|
||||||
maxPages = kMaxPages;
|
maxPages = kMaxPages;
|
||||||
|
|
||||||
|
const uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY
|
||||||
|
| HEAP_DONT_LOCK_KERNEL_SPACE;
|
||||||
|
|
||||||
PageWriteWrapper stackWrappers[2];
|
PageWriteWrapper stackWrappers[2];
|
||||||
PageWriteWrapper* wrapperPool = new(nogrow) PageWriteWrapper[maxPages + 1];
|
PageWriteWrapper* wrapperPool
|
||||||
|
= new(malloc_flags(allocationFlags)) PageWriteWrapper[maxPages + 1];
|
||||||
if (wrapperPool == NULL) {
|
if (wrapperPool == NULL) {
|
||||||
// don't fail, just limit our capabilities
|
// don't fail, just limit our capabilities
|
||||||
wrapperPool = stackWrappers;
|
wrapperPool = stackWrappers;
|
||||||
|
|||||||
Reference in New Issue
Block a user