l4lx: allocate memory in chunks

When L4Linux tries to allocate a dataspace of the size of its physical
memory, this allocation can fail, because the 'l4re_ma_alloc()' function
in the 'l4lx' library always tries to allocate a contiguous dataspace of
the given size and there might be no contiguous free area left.

With this patch, memory gets allocated in chunks: if the size to be
allocated exceeds the configured chunk size, a managed dataspace gets
created and filled with multiple memory chunks of at most the chunk size.

The chunk size is 16M by default and can be configured in an l4linux
config node:

<config args="...">
	<ram chunk_size="16M"/>
</config>

Fixes #695.
This commit is contained in:
Christian Prochaska 2013-03-19 14:59:10 +01:00 committed by Norman Feske
parent 3ae2c1712e
commit 570156b38c
3 changed files with 50 additions and 4 deletions

View File

@ -24,8 +24,9 @@ namespace Genode {
explicit Rm_session_client(Rm_session_capability session)
: Rpc_client<Rm_session>(session) { }
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset,
bool use_local_addr, Local_addr local_addr,
Local_addr attach(Dataspace_capability ds, size_t size = 0,
off_t offset = 0, bool use_local_addr = false,
Local_addr local_addr = 0,
bool executable = false)
{
return call<Rpc_attach>(ds, size, offset,

View File

@ -129,7 +129,7 @@ namespace Genode {
virtual Local_addr attach(Dataspace_capability ds,
size_t size = 0, off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (addr_t)0,
Local_addr local_addr = 0,
bool executable = false) = 0;
/**

View File

@ -14,6 +14,8 @@
/* Genode includes */
#include <base/printf.h>
#include <base/capability.h>
#include <os/config.h>
#include <rm_session/connection.h>
/* L4lx includes */
#include <dataspace.h>
@ -29,15 +31,58 @@ static const bool DEBUG = false;
extern "C" {
static const unsigned long _chunk_size()
{
enum { DEFAULT_CHUNK_SIZE = 16*1024*1024 };
Genode::Number_of_bytes result = DEFAULT_CHUNK_SIZE;
try {
Genode::config()->xml_node().sub_node("ram")
.attribute("chunk_size")
.value(&result);
} catch(...) { }
return result;
}
long l4re_ma_alloc(unsigned long size, l4re_ds_t const mem,
unsigned long flags)
{
static const unsigned long chunk_size = _chunk_size();
using namespace L4lx;
if (DEBUG)
PDBG("size=%lx mem=%lx flags=%lx", size, mem, flags);
Genode::Dataspace_capability cap = Genode::env()->ram_session()->alloc(size);
Genode::Dataspace_capability cap;
if (size > chunk_size) {
Genode::Rm_connection *rmc = new (Genode::env()->heap())
Genode::Rm_connection(0, size);
const unsigned long num_chunks = size / chunk_size;
const unsigned long remainder = size % chunk_size;
for (unsigned long i = 0; i < num_chunks; i++) {
Genode::Dataspace_capability cap =
Genode::env()->ram_session()->alloc(chunk_size);
rmc->attach(cap);
}
if (remainder > 0) {
Genode::Dataspace_capability cap =
Genode::env()->ram_session()->alloc(remainder);
rmc->attach(cap);
}
cap = rmc->dataspace();
} else {
cap = Genode::env()->ram_session()->alloc(size);
}
Dataspace *ds = new (Genode::env()->heap())
Dataspace("lx_memory", size, cap, mem);
Env::env()->dataspaces()->insert(ds);