Add swap and realloc to 'Attached_ram_dataspace'

The new 'swap' and 'realloc' functions are needed in scenarios where
'Attached_ram_dataspace' is used to implement double buffering. The
particular use case is the implementation of dynamic ROM sessions.
This commit is contained in:
Norman Feske
2012-04-04 21:20:28 +02:00
parent abb5a8a329
commit ba248fe554

View File

@@ -35,6 +35,33 @@ namespace Genode {
Ram_dataspace_capability _ds; Ram_dataspace_capability _ds;
void *_local_addr; void *_local_addr;
template <typename T>
static void _swap(T &v1, T &v2) { T tmp = v1; v1 = v2; v2 = tmp; }
void _detach_and_free_dataspace()
{
if (_local_addr)
env()->rm_session()->detach(_local_addr);
if (_ram_session && _ds.valid())
_ram_session->free(_ds);
}
void _alloc_and_attach()
{
if (!_size || !_ram_session) return;
try {
_ds = _ram_session->alloc(_size);
_local_addr = env()->rm_session()->attach(_ds);
/* revert allocation if attaching the dataspace failed */
} catch (Rm_session::Attach_failed) {
_ram_session->free(_ds);
throw;
}
}
public: public:
/** /**
@@ -44,27 +71,15 @@ namespace Genode {
* \throw Rm_session::Attach_failed * \throw Rm_session::Attach_failed
*/ */
Attached_ram_dataspace(Ram_session *ram_session, size_t size) Attached_ram_dataspace(Ram_session *ram_session, size_t size)
: _size(size), _ram_session(ram_session) : _size(size), _ram_session(ram_session), _local_addr(0)
{ {
try { _alloc_and_attach();
_ds = ram_session->alloc(size);
_local_addr = env()->rm_session()->attach(_ds);
/* revert allocation if attaching the dataspace failed */
} catch (Rm_session::Attach_failed) {
ram_session->free(_ds);
throw;
}
} }
/** /**
* Destructor * Destructor
*/ */
~Attached_ram_dataspace() ~Attached_ram_dataspace() { _detach_and_free_dataspace(); }
{
env()->rm_session()->detach(_local_addr);
_ram_session->free(_ds);
}
/** /**
* Return capability of the used RAM dataspace * Return capability of the used RAM dataspace
@@ -85,6 +100,31 @@ namespace Genode {
* Return size * Return size
*/ */
size_t size() const { return _size; } size_t size() const { return _size; }
void swap(Attached_ram_dataspace &other)
{
_swap(_size, other._size);
_swap(_ram_session, other._ram_session);
_swap(_ds, other._ds);
_swap(_local_addr, other._local_addr);
}
/**
* Re-allocate dataspace with a new size
*
* The content of the original dataspace is not retained.
*/
void realloc(Ram_session *ram_session, size_t new_size)
{
if (new_size < _size) return;
_detach_and_free_dataspace();
_size = new_size;
_ram_session = ram_session;
_alloc_and_attach();
}
}; };
} }