base: don't use the 'size' argument in 'Heap::free()'

The Heap reports that 'free()' does not rely on a valid 'size' argument,
so it should not use it.

Fixes #2113
This commit is contained in:
Christian Prochaska 2016-09-29 05:16:50 +02:00 committed by Christian Helmuth
parent ce2139a533
commit 3a1f852318
2 changed files with 57 additions and 46 deletions

View File

@ -64,6 +64,8 @@ class Genode::Heap : public Allocator
~Dataspace_pool();
void remove_and_free(Dataspace &);
void reassign_resources(Ram_session *ram, Region_map *rm) {
ram_session = ram, region_map = rm; }
};

View File

@ -36,33 +36,37 @@ namespace {
}
void Heap::Dataspace_pool::remove_and_free(Dataspace &ds)
{
/*
* read dataspace capability and modify _ds_list before detaching
* possible backing store for Dataspace - we rely on LIFO list
* manipulation here!
*/
Ram_dataspace_capability ds_cap = ds.cap;
void *ds_local_addr = ds.local_addr;
remove(&ds);
/*
* Call 'Dataspace' destructor to properly release the RAM dataspace
* capabilities. Note that we don't free the 'Dataspace' object at the
* local allocator because this is already done by the 'Heap'
* destructor prior executing the 'Dataspace_pool' destructor.
*/
ds.~Dataspace();
region_map->detach(ds_local_addr);
ram_session->free(ds_cap);
}
Heap::Dataspace_pool::~Dataspace_pool()
{
/* free all ram_dataspaces */
for (Dataspace *ds; (ds = first()); ) {
/*
* read dataspace capability and modify _ds_list before detaching
* possible backing store for Dataspace - we rely on LIFO list
* manipulation here!
*/
Ram_dataspace_capability ds_cap = ds->cap;
void *ds_local_addr = ds->local_addr;
remove(ds);
/*
* Call 'Dataspace' destructor to properly release the RAM dataspace
* capabilities. Note that we don't free the 'Dataspace' object at the
* local allocator because this is already done by the 'Heap'
* destructor prior executing the 'Dataspace_pool' destructor.
*/
ds->~Dataspace();
region_map->detach(ds_local_addr);
ram_session->free(ds_cap);
}
for (Dataspace *ds; (ds = first()); )
remove_and_free(*ds);
}
@ -216,37 +220,42 @@ bool Heap::alloc(size_t size, void **out_addr)
}
void Heap::free(void *addr, size_t size)
void Heap::free(void *addr, size_t)
{
/* serialize access of heap functions */
Lock::Guard lock_guard(_lock);
if (size >= BIG_ALLOCATION_THRESHOLD) {
/* try to find the size in our local allocator */
size_t const size = _alloc->size_at(addr);
Heap::Dataspace *ds;
if (size != 0) {
for (ds = _ds_pool.first(); ds; ds = ds->next())
if (((addr_t)addr >= (addr_t)ds->local_addr) &&
((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1))
break;
_ds_pool.remove(ds);
_ds_pool.region_map->detach(ds->local_addr);
_ds_pool.ram_session->free(ds->cap);
_quota_used -= ds->size;
destroy(*_alloc, ds);
} else {
/*
* forward request to our local allocator
*/
/* forward request to our local allocator */
_alloc->free(addr, size);
_quota_used -= size;
return;
}
/*
* Block could not be found in local allocator. So it is either a big
* allocation or invalid address.
*/
Heap::Dataspace *ds = nullptr;
for (ds = _ds_pool.first(); ds; ds = ds->next())
if (((addr_t)addr >= (addr_t)ds->local_addr) &&
((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1))
break;
if (!ds) {
warning("heap could not free memory block");
return;
}
_ds_pool.remove_and_free(*ds);
_alloc->free(ds);
_quota_used -= ds->size;
}