Added support for special reserved address ranges: they will be used

only if memory becomes tight, and then the range is used from end to
start.
This is useful to reserve heap address ranges.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12675 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-05-15 15:56:55 +00:00
parent 20a6e5473b
commit a3e9996e9d
3 changed files with 70 additions and 31 deletions
+20 -15
View File
@@ -43,23 +43,27 @@ void vm_put_aspace(vm_address_space *aspace);
// private kernel only extension (should be moved somewhere else): // private kernel only extension (should be moved somewhere else):
struct team; struct team;
area_id create_area_etc(struct team *team, const char *name, void **address, uint32 addressSpec, area_id create_area_etc(struct team *team, const char *name, void **address,
uint32 size, uint32 lock, uint32 protection); uint32 addressSpec, uint32 size, uint32 lock, uint32 protection);
status_t delete_area_etc(struct team *team, area_id area); status_t delete_area_etc(struct team *team, area_id area);
status_t vm_unreserve_address_range(aspace_id aid, void *address, addr_t size); status_t vm_unreserve_address_range(aspace_id aid, void *address, addr_t size);
status_t vm_reserve_address_range(aspace_id aid, void **_address, uint32 addressSpec, addr_t size); status_t vm_reserve_address_range(aspace_id aid, void **_address,
area_id vm_create_anonymous_area(aspace_id aid, const char *name, void **address, uint32 addressSpec, uint32 addressSpec, addr_t size, uint32 flags);
addr_t size, uint32 wiring, uint32 protection); area_id vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
area_id vm_map_physical_memory(aspace_id aid, const char *name, void **address, uint32 addressSpec, uint32 addressSpec, addr_t size, uint32 wiring, uint32 protection);
addr_t size, uint32 protection, addr_t phys_addr); area_id vm_map_physical_memory(aspace_id aid, const char *name, void **address,
area_id vm_map_file(aspace_id aid, const char *name, void **address, uint32 addressSpec, uint32 addressSpec, addr_t size, uint32 protection, addr_t phys_addr);
addr_t size, uint32 protection, uint32 mapping, const char *path, off_t offset); area_id vm_map_file(aspace_id aid, const char *name, void **address,
area_id vm_create_null_area(aspace_id aid, const char *name, void **address, uint32 addressSpec, addr_t size); uint32 addressSpec, addr_t size, uint32 protection, uint32 mapping,
area_id vm_copy_area(aspace_id addressSpaceID, const char *name, void **_address, uint32 addressSpec, const char *path, off_t offset);
uint32 protection, area_id sourceID); area_id vm_create_null_area(aspace_id aid, const char *name, void **address,
area_id vm_clone_area(aspace_id aid, const char *name, void **address, uint32 addressSpec, uint32 addressSpec, addr_t size);
uint32 protection, uint32 mapping, area_id sourceArea); area_id vm_copy_area(aspace_id addressSpaceID, const char *name, void **_address,
uint32 addressSpec, uint32 protection, area_id sourceID);
area_id vm_clone_area(aspace_id aid, const char *name, void **address,
uint32 addressSpec, uint32 protection, uint32 mapping,
area_id sourceArea);
status_t vm_delete_area(aspace_id aid, area_id id); status_t vm_delete_area(aspace_id aid, area_id id);
status_t vm_create_vnode_cache(void *vnode, vm_cache_ref **_cacheRef); status_t vm_create_vnode_cache(void *vnode, vm_cache_ref **_cacheRef);
@@ -77,7 +81,8 @@ area_id _user_find_area(const char *name);
status_t _user_get_area_info(area_id area, area_info *info); status_t _user_get_area_info(area_id area, area_info *info);
status_t _user_get_next_area_info(team_id team, int32 *cookie, area_info *info); status_t _user_get_next_area_info(team_id team, int32 *cookie, area_info *info);
status_t _user_resize_area(area_id area, size_t newSize); status_t _user_resize_area(area_id area, size_t newSize);
status_t _user_transfer_area(area_id area, void **_address, uint32 addressSpec, team_id target); status_t _user_transfer_area(area_id area, void **_address, uint32 addressSpec,
team_id target);
status_t _user_set_area_protection(area_id area, uint32 newProtection); status_t _user_set_area_protection(area_id area, uint32 newProtection);
area_id _user_clone_area(const char *name, void **_address, uint32 addressSpec, area_id _user_clone_area(const char *name, void **_address, uint32 addressSpec,
uint32 protection, area_id sourceArea); uint32 protection, area_id sourceArea);
+1 -1
View File
@@ -1278,7 +1278,7 @@ load_kernel_add_on(const char *path)
// reserve that space and allocate the areas from that one // reserve that space and allocate the areas from that one
if (vm_reserve_address_range(vm_get_kernel_aspace_id(), &reservedAddress, if (vm_reserve_address_range(vm_get_kernel_aspace_id(), &reservedAddress,
B_ANY_KERNEL_ADDRESS, reservedSize) < B_OK) B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK)
goto error3; goto error3;
start = (addr_t)reservedAddress; start = (addr_t)reservedAddress;
+49 -15
View File
@@ -117,7 +117,7 @@ vm_get_area(area_id id)
static vm_area * static vm_area *
_vm_create_reserved_region_struct(vm_virtual_map *map) _vm_create_reserved_region_struct(vm_virtual_map *map, uint32 flags)
{ {
vm_area *reserved = malloc(sizeof(vm_area)); vm_area *reserved = malloc(sizeof(vm_area));
if (reserved == NULL) if (reserved == NULL)
@@ -126,6 +126,7 @@ _vm_create_reserved_region_struct(vm_virtual_map *map)
memset(reserved, 0, sizeof(vm_area)); memset(reserved, 0, sizeof(vm_area));
reserved->id = RESERVED_AREA_ID; reserved->id = RESERVED_AREA_ID;
// this marks it as reserved space // this marks it as reserved space
reserved->protection = flags;
reserved->map = map; reserved->map = map;
return reserved; return reserved;
@@ -231,7 +232,7 @@ find_reserved_area(vm_virtual_map *map, addr_t start, addr_t size, vm_area *area
} else { } else {
// 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
vm_area *reserved = _vm_create_reserved_region_struct(map); vm_area *reserved = _vm_create_reserved_region_struct(map, 0);
if (reserved == NULL) if (reserved == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -261,7 +262,7 @@ find_and_insert_area_slot(vm_virtual_map *map, addr_t start, addr_t size, addr_t
{ {
vm_area *last = NULL; vm_area *last = NULL;
vm_area *next; vm_area *next;
bool foundspot = false; bool foundSpot = false;
TRACE(("find_and_insert_region_slot: map %p, start 0x%lx, size %ld, end 0x%lx, addressSpec %ld, area %p\n", TRACE(("find_and_insert_region_slot: map %p, start 0x%lx, size %ld, end 0x%lx, addressSpec %ld, area %p\n",
map, start, size, end, addressSpec, area)); map, start, size, end, addressSpec, area));
@@ -294,6 +295,9 @@ second_chance:
next = next->aspace_next; next = next->aspace_next;
} }
// find the right spot depending on the address specification - the area
// will be inserted directly after "last" ("next" is not referenced anymore)
switch (addressSpec) { switch (addressSpec) {
case B_ANY_ADDRESS: case B_ANY_ADDRESS:
case B_ANY_KERNEL_ADDRESS: case B_ANY_KERNEL_ADDRESS:
@@ -302,7 +306,7 @@ second_chance:
if (!last) { if (!last) {
// see if we can build it at the beginning of the virtual map // see if we can build it at the beginning of the virtual map
if (!next || (next->base >= map->base + size)) { if (!next || (next->base >= map->base + size)) {
foundspot = true; foundSpot = true;
area->base = map->base; area->base = map->base;
break; break;
} }
@@ -321,9 +325,39 @@ second_chance:
if ((map->base + (map->size - 1)) >= (last->base + last->size + (size - 1))) { if ((map->base + (map->size - 1)) >= (last->base + last->size + (size - 1))) {
// got a spot // got a spot
foundspot = true; foundSpot = true;
area->base = last->base + last->size; area->base = last->base + last->size;
break; break;
} else {
// we didn't find a free spot - if there were any reserved areas with
// the RESERVED_AVOID_BASE flag set, we can now test those for free
// space
// ToDo: it would make sense to start with the biggest of them
next = map->areas;
last = NULL;
for (last = NULL; next; next = next->aspace_next, last = next) {
if (next->size == size) {
// the reserved area is entirely covered, and thus, removed
if (last)
last->aspace_next = next->aspace_next;
else
map->areas = next->aspace_next;
foundSpot = true;
area->base = next->base;
free(next);
break;
}
if (next->size >= size) {
// the new area will be placed at the end of the reserved
// area, and the reserved area will be resized to make space
foundSpot = true;
next->size -= size;
last = next;
area->base = next->base + next->size;
break;
}
}
} }
break; break;
@@ -332,7 +366,7 @@ second_chance:
if (!last) { if (!last) {
// see if we can build it at the beginning of the specified start // see if we can build it at the beginning of the specified start
if (!next || (next->base >= start + size)) { if (!next || (next->base >= start + size)) {
foundspot = true; foundSpot = true;
area->base = start; area->base = start;
break; break;
} }
@@ -351,7 +385,7 @@ second_chance:
if ((map->base + (map->size - 1)) >= (last->base + last->size + (size - 1))) { if ((map->base + (map->size - 1)) >= (last->base + last->size + (size - 1))) {
// got a spot // got a spot
foundspot = true; foundSpot = true;
if (last->base + last->size <= start) if (last->base + last->size <= start)
area->base = start; area->base = start;
else else
@@ -369,20 +403,20 @@ second_chance:
// see if we can create it exactly here // see if we can create it exactly here
if (!last) { if (!last) {
if (!next || (next->base >= start + size)) { if (!next || (next->base >= start + size)) {
foundspot = true; foundSpot = true;
area->base = start; area->base = start;
break; break;
} }
} else { } else {
if (next) { if (next) {
if (last->base + last->size <= start && next->base >= start + size) { if (last->base + last->size <= start && next->base >= start + size) {
foundspot = true; foundSpot = true;
area->base = start; area->base = start;
break; break;
} }
} else { } else {
if ((last->base + (last->size - 1)) <= start - 1) { if ((last->base + (last->size - 1)) <= start - 1) {
foundspot = true; foundSpot = true;
area->base = start; area->base = start;
} }
} }
@@ -392,7 +426,7 @@ second_chance:
return B_BAD_VALUE; return B_BAD_VALUE;
} }
if (!foundspot) if (!foundSpot)
return addressSpec == B_EXACT_ADDRESS ? B_BAD_VALUE : B_NO_MEMORY; return addressSpec == B_EXACT_ADDRESS ? B_BAD_VALUE : B_NO_MEMORY;
area->size = size; area->size = size;
@@ -616,7 +650,7 @@ out:
status_t status_t
vm_reserve_address_range(aspace_id aid, void **_address, uint32 addressSpec, addr_t size) vm_reserve_address_range(aspace_id aid, void **_address, uint32 addressSpec, addr_t size, uint32 flags)
{ {
vm_address_space *addressSpace; vm_address_space *addressSpace;
vm_area *area; vm_area *area;
@@ -629,7 +663,7 @@ vm_reserve_address_range(aspace_id aid, void **_address, uint32 addressSpec, add
if (addressSpace == NULL) if (addressSpace == NULL)
return B_BAD_TEAM_ID; return B_BAD_TEAM_ID;
area = _vm_create_reserved_region_struct(&addressSpace->virtual_map); area = _vm_create_reserved_region_struct(&addressSpace->virtual_map, flags);
if (area == NULL) { if (area == NULL) {
status = B_NO_MEMORY; status = B_NO_MEMORY;
goto err1; goto err1;
@@ -2042,7 +2076,7 @@ reserve_boot_loader_ranges(kernel_args *args)
for (i = 0; i < args->num_virtual_allocated_ranges; i++) { for (i = 0; i < args->num_virtual_allocated_ranges; i++) {
void *address = (void *)args->virtual_allocated_range[i].start; void *address = (void *)args->virtual_allocated_range[i].start;
status_t status = vm_reserve_address_range(vm_get_kernel_aspace_id(), &address, status_t status = vm_reserve_address_range(vm_get_kernel_aspace_id(), &address,
B_EXACT_ADDRESS, args->virtual_allocated_range[i].size); B_EXACT_ADDRESS, args->virtual_allocated_range[i].size, 0);
if (status < B_OK) if (status < B_OK)
panic("could not reserve boot loader ranges\n"); panic("could not reserve boot loader ranges\n");
} }
@@ -3091,7 +3125,7 @@ transfer_area(area_id id, void **_address, uint32 addressSpec, team_id target)
sourceAddressSpace = area->aspace; sourceAddressSpace = area->aspace;
reserved = _vm_create_reserved_region_struct(&sourceAddressSpace->virtual_map); reserved = _vm_create_reserved_region_struct(&sourceAddressSpace->virtual_map, 0);
if (reserved == NULL) { if (reserved == NULL) {
status = B_NO_MEMORY; status = B_NO_MEMORY;
goto err2; goto err2;