[Haiku-commits] r31115 - in haiku/trunk: headers/private/kernel headers/private/system src/kits/app src/system/kernel/vm src/system/libroot/posix/malloc src/system/runtime_loader
axeld at BerliOS
axeld at mail.berlios.de
Fri Jun 19 13:09:23 CEST 2009
Author: axeld
Date: 2009-06-19 13:09:21 +0200 (Fri, 19 Jun 2009)
New Revision: 31115
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31115&view=rev
Modified:
haiku/trunk/headers/private/kernel/vm.h
haiku/trunk/headers/private/system/syscalls.h
haiku/trunk/src/kits/app/ServerMemoryAllocator.cpp
haiku/trunk/src/system/kernel/vm/vm.cpp
haiku/trunk/src/system/libroot/posix/malloc/arch-specific.cpp
haiku/trunk/src/system/runtime_loader/images.cpp
Log:
* Renamed _kern_reserve_heap_address_range() to _kern_reserve_address_range(),
and added a _kern_unreserve_address_range() as well.
* The runtime loader now reserves the space needed for all its areas first
to make sure there is enough space left for all areas of a single image.
* This also fixes the final part of bug #4008.
* Minor cleanup.
Modified: haiku/trunk/headers/private/kernel/vm.h
===================================================================
--- haiku/trunk/headers/private/kernel/vm.h 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/headers/private/kernel/vm.h 2009-06-19 11:09:21 UTC (rev 31115)
@@ -139,8 +139,9 @@
status_t _user_set_area_protection(area_id area, uint32 newProtection);
area_id _user_clone_area(const char *name, void **_address, uint32 addressSpec,
uint32 protection, area_id sourceArea);
-status_t _user_reserve_heap_address_range(addr_t* userAddress, uint32 addressSpec,
+status_t _user_reserve_address_range(addr_t* userAddress, uint32 addressSpec,
addr_t size);
+status_t _user_unreserve_address_range(addr_t address, addr_t size);
#ifdef __cplusplus
}
Modified: haiku/trunk/headers/private/system/syscalls.h
===================================================================
--- haiku/trunk/headers/private/system/syscalls.h 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/headers/private/system/syscalls.h 2009-06-19 11:09:21 UTC (rev 31115)
@@ -373,8 +373,9 @@
extern area_id _kern_clone_area(const char *name, void **_address,
uint32 addressSpec, uint32 protection,
area_id sourceArea);
-extern status_t _kern_reserve_heap_address_range(addr_t* _address,
+extern status_t _kern_reserve_address_range(addr_t* _address,
uint32 addressSpec, addr_t size);
+extern status_t _kern_unreserve_address_range(addr_t address, addr_t size);
extern area_id _kern_map_file(const char *name, void **address,
int addressSpec, size_t size, int protection,
Modified: haiku/trunk/src/kits/app/ServerMemoryAllocator.cpp
===================================================================
--- haiku/trunk/src/kits/app/ServerMemoryAllocator.cpp 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/src/kits/app/ServerMemoryAllocator.cpp 2009-06-19 11:09:21 UTC (rev 31115)
@@ -1,13 +1,12 @@
/*
- * Copyright 2006, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld at pinc-software.de
*/
-/*!
- Note, this class don't provide any locking whatsoever - you are
+/*! Note, this class don't provide any locking whatsoever - you are
supposed to have a BPrivate::AppServerLink object around which
does the necessary locking.
However, this is not enforced in the methods here, you have to
@@ -74,14 +73,16 @@
if (!readOnly) {
// reserve 128 MB of space for the area
base = (void*)0x60000000;
- status = _kern_reserve_heap_address_range((addr_t*)&base,
- B_BASE_ADDRESS, 128 * 1024 * 1024);
+ status = _kern_reserve_address_range((addr_t*)&base, B_BASE_ADDRESS,
+ 128 * 1024 * 1024);
addressSpec = status == B_OK ? B_EXACT_ADDRESS : B_BASE_ADDRESS;
}
#endif
- mapping->local_area = clone_area(readOnly ? "server read-only memory" : "server_memory",
- &base, addressSpec, B_READ_AREA | (readOnly ? 0 : B_WRITE_AREA), serverArea);
+ mapping->local_area = clone_area(readOnly
+ ? "server read-only memory" : "server_memory",
+ &base, addressSpec,
+ B_READ_AREA | (readOnly ? 0 : B_WRITE_AREA), serverArea);
if (mapping->local_area < B_OK) {
status = mapping->local_area;
@@ -118,7 +119,8 @@
status_t
-ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area, uint8*& _base)
+ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area,
+ uint8*& _base)
{
for (int32 i = fAreas.CountItems(); i-- > 0;) {
area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i);
Modified: haiku/trunk/src/system/kernel/vm/vm.cpp
===================================================================
--- haiku/trunk/src/system/kernel/vm/vm.cpp 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/src/system/kernel/vm/vm.cpp 2009-06-19 11:09:21 UTC (rev 31115)
@@ -1632,7 +1632,7 @@
}
status = insert_area(addressSpace, _virtualAddress, addressSpec, size, area);
- if (status < B_OK)
+ if (status != B_OK)
goto err2;
// attach the cache to the area
@@ -1741,7 +1741,7 @@
status_t status = insert_area(locker.AddressSpace(), _address, addressSpec,
size, area);
- if (status < B_OK) {
+ if (status != B_OK) {
free(area);
return status;
}
@@ -5907,8 +5907,7 @@
status_t
-_user_reserve_heap_address_range(addr_t* userAddress, uint32 addressSpec,
- addr_t size)
+_user_reserve_address_range(addr_t* userAddress, uint32 addressSpec, addr_t size)
{
// filter out some unavailable values (for userland)
switch (addressSpec) {
@@ -5920,16 +5919,16 @@
addr_t address;
if (!IS_USER_ADDRESS(userAddress)
- || user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
+ || user_memcpy(&address, userAddress, sizeof(address)) != B_OK)
return B_BAD_ADDRESS;
status_t status = vm_reserve_address_range(
vm_current_user_address_space_id(), (void**)&address, addressSpec, size,
RESERVED_AVOID_BASE);
- if (status < B_OK)
+ if (status != B_OK)
return status;
- if (user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
+ if (user_memcpy(userAddress, &address, sizeof(address)) != B_OK) {
vm_unreserve_address_range(vm_current_user_address_space_id(),
(void*)address, size);
return B_BAD_ADDRESS;
@@ -5939,6 +5938,14 @@
}
+status_t
+_user_unreserve_address_range(addr_t address, addr_t size)
+{
+ return vm_unreserve_address_range(vm_current_user_address_space_id(),
+ (void*)address, size);
+}
+
+
area_id
_user_area_for(void* address)
{
Modified: haiku/trunk/src/system/libroot/posix/malloc/arch-specific.cpp
===================================================================
--- haiku/trunk/src/system/libroot/posix/malloc/arch-specific.cpp 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/src/system/libroot/posix/malloc/arch-specific.cpp 2009-06-19 11:09:21 UTC (rev 31115)
@@ -88,7 +88,7 @@
// for it. They may get reclaimed by other areas, though, but the maximum
// size of the heap is guaranteed until the space is really needed.
sHeapBase = (void *)0x18000000;
- status_t status = _kern_reserve_heap_address_range((addr_t *)&sHeapBase,
+ status_t status = _kern_reserve_address_range((addr_t *)&sHeapBase,
B_EXACT_ADDRESS, 0x48000000);
sHeapArea = create_area("heap", (void **)&sHeapBase,
Modified: haiku/trunk/src/system/runtime_loader/images.cpp
===================================================================
--- haiku/trunk/src/system/runtime_loader/images.cpp 2009-06-19 10:17:42 UTC (rev 31114)
+++ haiku/trunk/src/system/runtime_loader/images.cpp 2009-06-19 11:09:21 UTC (rev 31115)
@@ -154,6 +154,30 @@
}
+/*! Finds the load address and address specifier of the given image region.
+*/
+static void
+get_image_region_load_address(image_t* image, uint32 index, int32 lastDelta,
+ bool fixed, addr_t& loadAddress, uint32& addressSpecifier)
+{
+ if (image->dynamic_ptr != 0 && !fixed) {
+ // relocatable image... we can afford to place wherever
+ if (index == 0) {
+ // but only the first segment gets a free ride
+ loadAddress = RLD_PROGRAM_BASE;
+ addressSpecifier = B_BASE_ADDRESS;
+ } else {
+ loadAddress = image->regions[index].vmstart + lastDelta;
+ addressSpecifier = B_EXACT_ADDRESS;
+ }
+ } else {
+ // not relocatable, put it where it asks or die trying
+ loadAddress = image->regions[index].vmstart;
+ addressSpecifier = B_EXACT_ADDRESS;
+ }
+}
+
+
// #pragma mark -
@@ -260,74 +284,95 @@
else
baseName = path;
+ // determine how much space we need for all loaded segments
+
+ addr_t reservedAddress = 0;
+ addr_t loadAddress;
+ size_t reservedSize = 0;
+ size_t length = 0;
+ uint32 addressSpecifier = B_ANY_ADDRESS;
+
for (uint32 i = 0; i < image->num_regions; i++) {
- char regionName[B_OS_NAME_LENGTH];
- addr_t loadAddress;
- uint32 addressSpecifier;
-
// for BeOS compatibility: if we load an old BeOS executable, we
// have to relocate it, if possible - we recognize it because the
// vmstart is set to 0 (hopefully always)
if (fixed && image->regions[i].vmstart == 0)
fixed = false;
+ uint32 regionAddressSpecifier;
+ get_image_region_load_address(image, i,
+ loadAddress - image->regions[i - 1].vmstart, fixed,
+ loadAddress, regionAddressSpecifier);
+ if (i == 0) {
+ reservedAddress = loadAddress;
+ addressSpecifier = regionAddressSpecifier;
+ }
+
+ length += TO_PAGE_SIZE(image->regions[i].vmsize
+ + (loadAddress % B_PAGE_SIZE));
+
+ size_t size = TO_PAGE_SIZE(loadAddress + image->regions[i].vmsize)
+ - reservedAddress;
+ if (size > reservedSize)
+ reservedSize = size;
+ }
+
+ // Check whether the segments have an unreasonable amount of unused space
+ // inbetween.
+ if (reservedSize > length + 8 * 1024)
+ return B_BAD_DATA;
+
+ // reserve that space and allocate the areas from that one
+ if (_kern_reserve_address_range(&reservedAddress, addressSpecifier,
+ reservedSize) != B_OK)
+ return B_NO_MEMORY;
+
+ for (uint32 i = 0; i < image->num_regions; i++) {
+ char regionName[B_OS_NAME_LENGTH];
+
snprintf(regionName, sizeof(regionName), "%s_seg%lu%s",
baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro");
- if (image->dynamic_ptr && !fixed) {
- // relocatable image... we can afford to place wherever
- if (i == 0) {
- // but only the first segment gets a free ride
- loadAddress = RLD_PROGRAM_BASE;
- addressSpecifier = B_BASE_ADDRESS;
- } else {
- loadAddress = image->regions[i].vmstart
- + image->regions[i-1].delta;
- addressSpecifier = B_EXACT_ADDRESS;
- }
- } else {
- // not relocatable, put it where it asks or die trying
- loadAddress = image->regions[i].vmstart;
- addressSpecifier = B_EXACT_ADDRESS;
- }
+ get_image_region_load_address(image, i, image->regions[i - 1].delta,
+ fixed, loadAddress, addressSpecifier);
- if (image->regions[i].flags & RFLAG_ANON) {
+ // If the image position is arbitrary, we must let it point to the start
+ // of the reserved address range.
+ if (addressSpecifier != B_EXACT_ADDRESS)
+ loadAddress = reservedAddress;
+
+ if ((image->regions[i].flags & RFLAG_ANON) != 0) {
image->regions[i].id = _kern_create_area(regionName,
- (void**)&loadAddress, addressSpecifier,
+ (void**)&loadAddress, B_EXACT_ADDRESS,
image->regions[i].vmsize, B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA);
- if (image->regions[i].id < 0)
+ if (image->regions[i].id < 0) {
+ _kern_unreserve_address_range(reservedAddress, reservedSize);
return image->regions[i].id;
-
- image->regions[i].delta = loadAddress - image->regions[i].vmstart;
- image->regions[i].vmstart = loadAddress;
+ }
} else {
image->regions[i].id = _kern_map_file(regionName,
- (void**)&loadAddress, addressSpecifier,
+ (void**)&loadAddress, B_EXACT_ADDRESS,
image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA,
REGION_PRIVATE_MAP, false, fd,
PAGE_BASE(image->regions[i].fdstart));
- if (image->regions[i].id < 0)
+ if (image->regions[i].id < 0) {
+ _kern_unreserve_address_range(reservedAddress, reservedSize);
return image->regions[i].id;
+ }
TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path,
(void *)loadAddress, image->regions[i].vmsize,
image->regions[i].flags & RFLAG_RW ? "rw" : "read-only"));
- image->regions[i].delta = loadAddress - image->regions[i].vmstart;
- image->regions[i].vmstart = loadAddress;
-
// handle trailer bits in data segment
if (image->regions[i].flags & RFLAG_RW) {
- addr_t startClearing;
- addr_t toClear;
-
- startClearing = image->regions[i].vmstart
+ addr_t startClearing = loadAddress
+ PAGE_OFFSET(image->regions[i].start)
+ image->regions[i].size;
- toClear = image->regions[i].vmsize
+ addr_t toClear = image->regions[i].vmsize
- PAGE_OFFSET(image->regions[i].start)
- image->regions[i].size;
@@ -336,9 +381,12 @@
memset((void *)startClearing, 0, toClear);
}
}
+
+ image->regions[i].delta = loadAddress - image->regions[i].vmstart;
+ image->regions[i].vmstart = loadAddress;
}
- if (image->dynamic_ptr)
+ if (image->dynamic_ptr != 0)
image->dynamic_ptr += image->regions[0].delta;
return B_OK;
More information about the Haiku-commits
mailing list