Io_mem_session, fix #128

Free unaligned ranges correctly in range allocator
This commit is contained in:
Sebastian Sumpf 2012-02-25 21:21:57 +01:00 committed by Norman Feske
parent a9152ff412
commit b6e355b841
2 changed files with 32 additions and 21 deletions

View File

@ -40,13 +40,18 @@ namespace Genode {
addr_t phys_addr;
bool write_combined;
/**
* Base address of request used for freeing mem-ranges
*/
addr_t req_base;
/**
* Default constructor
*
* This constructor enables Dataspace_attr objects to be
* returned from the '_prepare_io_mem' function.
*/
Dataspace_attr() { }
Dataspace_attr() : size(0) { }
/**
* Constructor
@ -54,24 +59,28 @@ namespace Genode {
* An invalid dataspace is represented by setting all
* arguments to zero.
*/
Dataspace_attr(size_t s, addr_t cla, addr_t pa, bool write_combined):
size(s), core_local_addr(cla), phys_addr(pa) { }
Dataspace_attr(size_t s, addr_t cla, addr_t pa, bool write_combined,
addr_t req_base)
:
size(s), core_local_addr(cla), phys_addr(pa), req_base(req_base) { }
};
} ds_attr;
class Io_dataspace_component : public Dataspace_component
struct Io_dataspace_component : Dataspace_component
{
public:
addr_t req_base;
/**
* Constructor
*/
Io_dataspace_component(Dataspace_attr da)
: Dataspace_component(da.size, da.core_local_addr,
da.phys_addr, da.write_combined,
true) { }
/**
* Constructor
*/
Io_dataspace_component(Dataspace_attr da)
:
Dataspace_component(da.size, da.core_local_addr,
da.phys_addr, da.write_combined,
true),
req_base(da.req_base) { }
bool valid() { return size() != 0; }
bool valid() { return size() != 0; }
};
Range_allocator *_io_mem_alloc;

View File

@ -16,7 +16,7 @@
#include <root/root.h>
#include <dataspace_component.h>
#include <io_mem_session_component.h>
#include <base/allocator_avl.h>
#include "util.h"
using namespace Genode;
@ -47,18 +47,18 @@ Io_mem_session_component::_prepare_io_mem(const char *args,
int ret;
if ((ret = ram_alloc->remove_range(base, size))) {
PERR("I/O memory [%lx,%lx) used by RAM allocator (%d)", base, base + size, ret);
return Dataspace_attr(0, 0, 0, 0);
return Dataspace_attr();
}
/* allocate region */
switch (_io_mem_alloc->alloc_addr(req_size, req_base)) {
case Range_allocator::RANGE_CONFLICT:
PERR("I/O memory [%lx,%lx) not available", base, base + size);
return Dataspace_attr(0, 0, 0, 0);
return Dataspace_attr();
case Range_allocator::OUT_OF_METADATA:
PERR("I/O memory allocator ran out of meta data");
return Dataspace_attr(0, 0, 0, 0);
return Dataspace_attr();
case Range_allocator::ALLOC_OK: break;
}
@ -71,7 +71,7 @@ Io_mem_session_component::_prepare_io_mem(const char *args,
base, base + size, local_addr, local_addr + size,
_write_combined ? " (write-combined)" : "");
return Dataspace_attr(size, local_addr, base, _write_combined);
return Dataspace_attr(size, local_addr, base, _write_combined, req_base);
}
@ -97,6 +97,8 @@ Io_mem_session_component::Io_mem_session_component(Range_allocator *io_mem_alloc
Io_mem_session_component::~Io_mem_session_component()
{
if (verbose)
PDBG("I/O mem free [%lx,%lx)", _ds.phys_addr(), _ds.phys_addr() + _ds.size());
/* dissolve IO_MEM dataspace from service entry point */
_ds_ep->dissolve(&_ds);
@ -110,5 +112,5 @@ Io_mem_session_component::~Io_mem_session_component()
*/
/* free region in IO_MEM allocator */
_io_mem_alloc->free(reinterpret_cast<void *>(_ds.phys_addr()));
_io_mem_alloc->free(reinterpret_cast<void *>(_ds.req_base));
}