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(); ~Dataspace_pool();
void remove_and_free(Dataspace &);
void reassign_resources(Ram_session *ram, Region_map *rm) { void reassign_resources(Ram_session *ram, Region_map *rm) {
ram_session = ram, region_map = rm; } ram_session = ram, region_map = rm; }
}; };

View File

@ -36,21 +36,18 @@ namespace {
} }
Heap::Dataspace_pool::~Dataspace_pool() void Heap::Dataspace_pool::remove_and_free(Dataspace &ds)
{ {
/* free all ram_dataspaces */
for (Dataspace *ds; (ds = first()); ) {
/* /*
* read dataspace capability and modify _ds_list before detaching * read dataspace capability and modify _ds_list before detaching
* possible backing store for Dataspace - we rely on LIFO list * possible backing store for Dataspace - we rely on LIFO list
* manipulation here! * manipulation here!
*/ */
Ram_dataspace_capability ds_cap = ds->cap; Ram_dataspace_capability ds_cap = ds.cap;
void *ds_local_addr = ds->local_addr; void *ds_local_addr = ds.local_addr;
remove(ds); remove(&ds);
/* /*
* Call 'Dataspace' destructor to properly release the RAM dataspace * Call 'Dataspace' destructor to properly release the RAM dataspace
@ -58,11 +55,18 @@ Heap::Dataspace_pool::~Dataspace_pool()
* local allocator because this is already done by the 'Heap' * local allocator because this is already done by the 'Heap'
* destructor prior executing the 'Dataspace_pool' destructor. * destructor prior executing the 'Dataspace_pool' destructor.
*/ */
ds->~Dataspace(); ds.~Dataspace();
region_map->detach(ds_local_addr); region_map->detach(ds_local_addr);
ram_session->free(ds_cap); ram_session->free(ds_cap);
} }
Heap::Dataspace_pool::~Dataspace_pool()
{
/* free all ram_dataspaces */
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 */ /* serialize access of heap functions */
Lock::Guard lock_guard(_lock); 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) {
/* 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()) for (ds = _ds_pool.first(); ds; ds = ds->next())
if (((addr_t)addr >= (addr_t)ds->local_addr) && if (((addr_t)addr >= (addr_t)ds->local_addr) &&
((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1)) ((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1))
break; break;
_ds_pool.remove(ds); if (!ds) {
_ds_pool.region_map->detach(ds->local_addr); warning("heap could not free memory block");
_ds_pool.ram_session->free(ds->cap); return;
}
_ds_pool.remove_and_free(*ds);
_alloc->free(ds);
_quota_used -= ds->size; _quota_used -= ds->size;
destroy(*_alloc, ds);
} else {
/*
* forward request to our local allocator
*/
_alloc->free(addr, size);
_quota_used -= size;
}
} }