[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