* Added a "flags" parameter to vm_create_anonymous_area() and
create_area_etc(). * When the new flag CREATE_AREA_DONT_WAIT is specified, the functions don't wait for memory or pages to become available. They fail immediately instead. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27117 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,6 +23,11 @@ struct vm_address_space;
|
|||||||
struct vnode;
|
struct vnode;
|
||||||
|
|
||||||
|
|
||||||
|
// area creation flags
|
||||||
|
#define CREATE_AREA_DONT_WAIT 0x01
|
||||||
|
#define CREATE_AREA_UNMAP_ADDRESS_RANGE 0x02
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -48,14 +53,15 @@ void forbid_page_faults(void);
|
|||||||
|
|
||||||
// private kernel only extension (should be moved somewhere else):
|
// private kernel only extension (should be moved somewhere else):
|
||||||
area_id create_area_etc(team_id team, const char *name, void **address,
|
area_id create_area_etc(team_id team, const char *name, void **address,
|
||||||
uint32 addressSpec, uint32 size, uint32 lock, uint32 protection);
|
uint32 addressSpec, uint32 size, uint32 lock, uint32 protection,
|
||||||
|
uint32 flags);
|
||||||
|
|
||||||
status_t vm_unreserve_address_range(team_id team, void *address, addr_t size);
|
status_t vm_unreserve_address_range(team_id team, void *address, addr_t size);
|
||||||
status_t vm_reserve_address_range(team_id team, void **_address,
|
status_t vm_reserve_address_range(team_id team, void **_address,
|
||||||
uint32 addressSpec, addr_t size, uint32 flags);
|
uint32 addressSpec, addr_t size, uint32 flags);
|
||||||
area_id vm_create_anonymous_area(team_id team, const char *name, void **address,
|
area_id vm_create_anonymous_area(team_id team, const char *name, void **address,
|
||||||
uint32 addressSpec, addr_t size, uint32 wiring, uint32 protection,
|
uint32 addressSpec, addr_t size, uint32 wiring, uint32 protection,
|
||||||
bool unmapAddressRange, bool kernel);
|
uint32 flags, bool kernel);
|
||||||
area_id vm_map_physical_memory(team_id team, const char *name, void **address,
|
area_id vm_map_physical_memory(team_id team, const char *name, void **address,
|
||||||
uint32 addressSpec, addr_t size, uint32 protection, addr_t phys_addr);
|
uint32 addressSpec, addr_t size, uint32 protection, addr_t phys_addr);
|
||||||
area_id vm_map_file(team_id aid, const char *name, void **address,
|
area_id vm_map_file(team_id aid, const char *name, void **address,
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ vm86_prepare(struct vm86_state *state, unsigned int ramSize)
|
|||||||
|
|
||||||
void *address = (void *)0;
|
void *address = (void *)0;
|
||||||
state->ram_area = create_area_etc(team->id, "dos", &address,
|
state->ram_area = create_area_etc(team->id, "dos", &address,
|
||||||
B_EXACT_ADDRESS, ramSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
B_EXACT_ADDRESS, ramSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA, 0);
|
||||||
if (state->ram_area < B_OK) {
|
if (state->ram_area < B_OK) {
|
||||||
ret = state->ram_area;
|
ret = state->ram_area;
|
||||||
TRACE("Could not create RAM area\n");
|
TRACE("Could not create RAM area\n");
|
||||||
|
|||||||
@@ -1470,7 +1470,7 @@ elf_load_user_image(const char *path, struct team *team, int flags,
|
|||||||
regionAddress += fileUpperBound;
|
regionAddress += fileUpperBound;
|
||||||
id = create_area_etc(team->id, regionName,
|
id = create_area_etc(team->id, regionName,
|
||||||
(void **)®ionAddress, B_EXACT_ADDRESS, bssSize,
|
(void **)®ionAddress, B_EXACT_ADDRESS, bssSize,
|
||||||
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA, 0);
|
||||||
if (id < B_OK) {
|
if (id < B_OK) {
|
||||||
dprintf("error allocating bss area: %s!\n", strerror(id));
|
dprintf("error allocating bss area: %s!\n", strerror(id));
|
||||||
status = B_NOT_AN_EXECUTABLE;
|
status = B_NOT_AN_EXECUTABLE;
|
||||||
|
|||||||
@@ -816,7 +816,7 @@ create_team_user_data(struct team* team)
|
|||||||
void* address = (void*)KERNEL_USER_DATA_BASE;
|
void* address = (void*)KERNEL_USER_DATA_BASE;
|
||||||
size_t size = 4 * B_PAGE_SIZE;
|
size_t size = 4 * B_PAGE_SIZE;
|
||||||
team->user_data_area = create_area_etc(team->id, "user area", &address,
|
team->user_data_area = create_area_etc(team->id, "user area", &address,
|
||||||
B_BASE_ADDRESS, size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
B_BASE_ADDRESS, size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA, 0);
|
||||||
if (team->user_data_area < 0)
|
if (team->user_data_area < 0)
|
||||||
return team->user_data_area;
|
return team->user_data_area;
|
||||||
|
|
||||||
@@ -996,7 +996,7 @@ team_create_thread_start(void *args)
|
|||||||
sprintf(ustack_name, "%s_main_stack", team->name);
|
sprintf(ustack_name, "%s_main_stack", team->name);
|
||||||
t->user_stack_area = create_area_etc(team->id, ustack_name,
|
t->user_stack_area = create_area_etc(team->id, ustack_name,
|
||||||
(void **)&t->user_stack_base, B_EXACT_ADDRESS, sizeLeft, B_NO_LOCK,
|
(void **)&t->user_stack_base, B_EXACT_ADDRESS, sizeLeft, B_NO_LOCK,
|
||||||
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
|
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA, 0);
|
||||||
if (t->user_stack_area < 0) {
|
if (t->user_stack_area < 0) {
|
||||||
dprintf("team_create_thread_start: could not create default user stack region\n");
|
dprintf("team_create_thread_start: could not create default user stack region\n");
|
||||||
|
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
|
|||||||
thread->user_stack_area = create_area_etc(team->id, stack_name,
|
thread->user_stack_area = create_area_etc(team->id, stack_name,
|
||||||
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
|
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
|
||||||
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
|
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
|
||||||
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
|
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA, 0);
|
||||||
if (thread->user_stack_area < B_OK
|
if (thread->user_stack_area < B_OK
|
||||||
|| arch_thread_init_tls(thread) < B_OK) {
|
|| arch_thread_init_tls(thread) < B_OK) {
|
||||||
// great, we have a fully running thread without a (usable)
|
// great, we have a fully running thread without a (usable)
|
||||||
|
|||||||
+27
-14
@@ -1628,7 +1628,7 @@ vm_reserve_address_range(team_id team, void **_address, uint32 addressSpec,
|
|||||||
area_id
|
area_id
|
||||||
vm_create_anonymous_area(team_id team, const char *name, void **address,
|
vm_create_anonymous_area(team_id team, const char *name, void **address,
|
||||||
uint32 addressSpec, addr_t size, uint32 wiring, uint32 protection,
|
uint32 addressSpec, addr_t size, uint32 wiring, uint32 protection,
|
||||||
bool unmapAddressRange, bool kernel)
|
uint32 flags, bool kernel)
|
||||||
{
|
{
|
||||||
vm_area *area;
|
vm_area *area;
|
||||||
vm_cache *cache;
|
vm_cache *cache;
|
||||||
@@ -1712,7 +1712,8 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
// won't be able to free anything for us.
|
// won't be able to free anything for us.
|
||||||
addr_t reservedMemory = 0;
|
addr_t reservedMemory = 0;
|
||||||
if (doReserveMemory) {
|
if (doReserveMemory) {
|
||||||
if (vm_try_reserve_memory(size, 1000000) != B_OK)
|
bigtime_t timeout = (flags & CREATE_AREA_DONT_WAIT) != 0 ? 0 : 1000000;
|
||||||
|
if (vm_try_reserve_memory(size, timeout) != B_OK)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
reservedMemory = size;
|
reservedMemory = size;
|
||||||
// TODO: We don't reserve the memory for the pages for the page
|
// TODO: We don't reserve the memory for the pages for the page
|
||||||
@@ -1722,18 +1723,28 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
// can get the VM into trouble in low memory situations.
|
// can get the VM into trouble in low memory situations.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddressSpaceWriteLocker locker;
|
||||||
|
vm_address_space *addressSpace;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
// For full lock areas reserve the pages before locking the address
|
// For full lock areas reserve the pages before locking the address
|
||||||
// space. E.g. block caches can't release their memory while we hold the
|
// space. E.g. block caches can't release their memory while we hold the
|
||||||
// address space lock.
|
// address space lock.
|
||||||
page_num_t reservedPages = reservedMapPages;
|
page_num_t reservedPages = reservedMapPages;
|
||||||
if (wiring == B_FULL_LOCK)
|
if (wiring == B_FULL_LOCK)
|
||||||
reservedPages += size / B_PAGE_SIZE;
|
reservedPages += size / B_PAGE_SIZE;
|
||||||
if (reservedPages > 0)
|
if (reservedPages > 0) {
|
||||||
vm_page_reserve_pages(reservedPages);
|
if ((flags & CREATE_AREA_DONT_WAIT) != 0) {
|
||||||
|
if (!vm_page_try_reserve_pages(reservedPages)) {
|
||||||
|
reservedPages = 0;
|
||||||
|
status = B_WOULD_BLOCK;
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
vm_page_reserve_pages(reservedPages);
|
||||||
|
}
|
||||||
|
|
||||||
AddressSpaceWriteLocker locker;
|
status = locker.SetTo(team);
|
||||||
vm_address_space *addressSpace;
|
|
||||||
status_t status = locker.SetTo(team);
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
@@ -1782,7 +1793,7 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
|
|
||||||
status = map_backing_store(addressSpace, cache, address, 0, size,
|
status = map_backing_store(addressSpace, cache, address, 0, size,
|
||||||
addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name,
|
addressSpec, wiring, protection, REGION_NO_PRIVATE_MAP, &area, name,
|
||||||
unmapAddressRange, kernel);
|
(flags & CREATE_AREA_UNMAP_ADDRESS_RANGE) != 0, kernel);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
cache->ReleaseRefAndUnlock();
|
cache->ReleaseRefAndUnlock();
|
||||||
@@ -2099,8 +2110,10 @@ _vm_map_file(team_id team, const char *name, void **_address, uint32 addressSpec
|
|||||||
protection |= B_SHARED_AREA;
|
protection |= B_SHARED_AREA;
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
uint32 flags = addressSpec == B_EXACT_ADDRESS
|
||||||
|
? CREATE_AREA_UNMAP_ADDRESS_RANGE : 0;
|
||||||
return vm_create_anonymous_area(team, name, _address, addressSpec, size,
|
return vm_create_anonymous_area(team, name, _address, addressSpec, size,
|
||||||
B_NO_LOCK, protection, addressSpec == B_EXACT_ADDRESS, kernel);
|
B_NO_LOCK, protection, flags, kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the open flags of the FD
|
// get the open flags of the FD
|
||||||
@@ -5564,12 +5577,13 @@ clone_area(const char *name, void **_address, uint32 addressSpec,
|
|||||||
|
|
||||||
area_id
|
area_id
|
||||||
create_area_etc(team_id team, const char *name, void **address,
|
create_area_etc(team_id team, const char *name, void **address,
|
||||||
uint32 addressSpec, uint32 size, uint32 lock, uint32 protection)
|
uint32 addressSpec, uint32 size, uint32 lock, uint32 protection,
|
||||||
|
uint32 flags)
|
||||||
{
|
{
|
||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
return vm_create_anonymous_area(team, (char *)name, address, addressSpec,
|
return vm_create_anonymous_area(team, (char *)name, address, addressSpec,
|
||||||
size, lock, protection, false, true);
|
size, lock, protection, flags, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5580,7 +5594,7 @@ create_area(const char *name, void **_address, uint32 addressSpec, size_t size,
|
|||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
return vm_create_anonymous_area(vm_kernel_address_space_id(), (char *)name, _address,
|
return vm_create_anonymous_area(vm_kernel_address_space_id(), (char *)name, _address,
|
||||||
addressSpec, size, lock, protection, false, true);
|
addressSpec, size, lock, protection, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5806,8 +5820,7 @@ _user_create_area(const char *userName, void **userAddress, uint32 addressSpec,
|
|||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
area_id area = vm_create_anonymous_area(vm_current_user_address_space_id(),
|
area_id area = vm_create_anonymous_area(vm_current_user_address_space_id(),
|
||||||
(char *)name, &address, addressSpec, size, lock, protection, false,
|
(char *)name, &address, addressSpec, size, lock, protection, 0, false);
|
||||||
false);
|
|
||||||
|
|
||||||
if (area >= B_OK && user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
|
if (area >= B_OK && user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
|
||||||
delete_area(area);
|
delete_area(area);
|
||||||
|
|||||||
Reference in New Issue
Block a user