Move Attach_*dataspace utils from os to base

Fixes #1958
This commit is contained in:
Norman Feske 2016-05-09 15:55:12 +02:00 committed by Christian Helmuth
parent 16914bddc8
commit 8d797105b3
10 changed files with 548 additions and 380 deletions

View File

@ -0,0 +1,109 @@
/*
* \brief Utility to attach a dataspace to the local address space
* \author Norman Feske
* \date 2014-01-10
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__ATTACHED_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_DATASPACE_H_
#include <dataspace/client.h>
#include <base/env.h>
namespace Genode { class Attached_dataspace; }
class Genode::Attached_dataspace : Noncopyable
{
public:
/**
* Exception type
*/
class Invalid_dataspace { };
private:
Dataspace_capability _ds;
size_t const _size = { Dataspace_client(_ds).size() };
void * _local_addr = nullptr;
Dataspace_capability _check(Dataspace_capability ds)
{
if (ds.valid())
return ds;
throw Invalid_dataspace();
}
public:
/**
* Constructor
*
* \throw Rm_session::Attach_failed
* \throw Invalid_dataspace
*/
Attached_dataspace(Region_map &rm, Dataspace_capability ds)
: _ds(_check(ds)), _local_addr(rm.attach(_ds)) { }
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with 'Region_map &' as first
* argument instead
*/
Attached_dataspace(Dataspace_capability ds)
: _ds(_check(ds)), _local_addr(env()->rm_session()->attach(_ds)) { }
/**
* Destructor
*/
~Attached_dataspace()
{
if (_local_addr)
env()->rm_session()->detach(_local_addr);
}
/**
* Return capability of the used dataspace
*/
Dataspace_capability cap() const { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at the caller.
* A newly attached dataspace is untyped memory anyway.
*/
template <typename T>
T *local_addr() { return static_cast<T *>(_local_addr); }
/**
* Return size
*/
size_t size() const { return _size; }
/**
* Forget dataspace, thereby skipping the detachment on destruction
*
* This method can be called if the the dataspace is known to be
* physically destroyed, e.g., because the session where the dataspace
* originated from was closed. In this case, core will already have
* removed the memory mappings of the dataspace. So we have to omit the
* detach operation in '~Attached_dataspace'.
*/
void invalidate() { _local_addr = nullptr; }
};
#endif /* _INCLUDE__BASE__ATTACHED_DATASPACE_H_ */

View File

@ -0,0 +1,104 @@
/*
* \brief I/O MEM dataspace utility
* \author Norman Feske
* \date 2011-05-19
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_
#include <io_mem_session/connection.h>
#include <base/env.h>
namespace Genode { class Attached_io_mem_dataspace; }
/**
* Request and locally attach a memory-mapped I/O resource
*
* This class is a wrapper for a typical sequence of operations performed
* by device drivers to access memory-mapped device resources. Its sole
* purpose is to avoid duplicated code.
*/
class Genode::Attached_io_mem_dataspace
{
private:
Region_map &_env_rm;
Io_mem_connection _mmio;
Io_mem_dataspace_capability _ds;
void *_local_addr;
public:
/**
* Constructor
*
* \param base base address of memory-mapped I/O resource
* \param size size of resource
* \param write_combined enable write combining for the resource
*
* \throw Parent::Service_denied
* \throw Parent::Quota_exceeded
* \throw Parent::Unavailable
* \throw Rm_session::Attach_failed
*/
Attached_io_mem_dataspace(Env &env, Genode::addr_t base, Genode::size_t size,
bool write_combined = false)
:
_env_rm(env.rm()),
_mmio(env, base, size, write_combined),
_ds(_mmio.dataspace()),
_local_addr(env.rm().attach(_ds))
{
/* apply sub-page offset to virtual address */
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
}
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with 'Env &' as first
* argument instead
*/
Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size,
bool write_combined = false)
:
_env_rm(*env()->rm_session()),
_mmio(base, size, write_combined),
_ds(_mmio.dataspace()),
_local_addr(_env_rm.attach(_ds))
{
/* apply sub-page offset to virtual address */
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
}
/**
* Destructor
*/
~Attached_io_mem_dataspace() { _env_rm.detach(_local_addr); }
/**
* Return capability of the used RAM dataspace
*/
Io_mem_dataspace_capability cap() { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at the caller.
* A newly allocated I/O MEM dataspace is untyped memory anyway.
*/
template <typename T>
T *local_addr() { return static_cast<T *>(_local_addr); }
};
#endif /* _INCLUDE__BASE__ATTACHED_IO_MEM_DATASPACE_H_ */

View File

@ -0,0 +1,170 @@
/*
* \brief Utility to allocate and locally attach a RAM dataspace
* \author Norman Feske
* \date 2008-03-22
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
#include <ram_session/ram_session.h>
#include <util/touch.h>
#include <base/env.h>
namespace Genode { class Attached_ram_dataspace; }
/*
* Utility for allocating and attaching a RAM dataspace
*
* The combination of RAM allocation and a local RM attachment is a frequent
* use case. Each function may fail, which makes error handling inevitable.
* This utility class encapsulates this functionality to handle both operations
* as a transaction. When embedded as a member, this class also takes care
* about freeing and detaching the dataspace at destruction time.
*/
class Genode::Attached_ram_dataspace
{
private:
size_t _size;
Ram_session *_ram;
Region_map *_rm;
Ram_dataspace_capability _ds;
void *_local_addr = nullptr;
Cache_attribute const _cached;
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)
_rm->detach(_local_addr);
if (_ds.valid())
_ram->free(_ds);
}
void _alloc_and_attach()
{
if (!_size) return;
try {
_ds = _ram->alloc(_size, _cached);
_local_addr = _rm->attach(_ds);
/* revert allocation if attaching the dataspace failed */
} catch (Region_map::Attach_failed) {
_ram->free(_ds);
throw;
}
/*
* Eagerly map dataspace if used for DMA
*
* On some platforms, namely Fiasco.OC on ARMv7, the handling
* of page faults interferes with the caching attributes used
* for uncached DMA memory. See issue #452 for more details
* (https://github.com/genodelabs/genode/issues/452). As a
* work-around for this issues, we eagerly map the whole
* dataspace before writing actual content to it.
*/
if (_cached != CACHED) {
enum { PAGE_SIZE = 4096 };
unsigned char volatile *base = (unsigned char volatile *)_local_addr;
for (size_t i = 0; i < _size; i += PAGE_SIZE)
touch_read_write(base + i);
}
}
public:
/**
* Constructor
*
* \throw Ram_session::Alloc_failed
* \throw Rm_session::Attach_failed
*/
Attached_ram_dataspace(Ram_session &ram, Region_map &rm,
size_t size, Cache_attribute cached = CACHED)
:
_size(size), _ram(&ram), _rm(&rm), _cached(cached)
{
_alloc_and_attach();
}
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with the 'Ram_session &' and
* 'Region_map &' arguments instead.
*/
Attached_ram_dataspace(Ram_session *ram, size_t size,
Cache_attribute cached = CACHED)
:
_size(size), _ram(ram), _rm(env()->rm_session()), _cached(cached)
{
_alloc_and_attach();
}
/**
* Destructor
*/
~Attached_ram_dataspace() { _detach_and_free_dataspace(); }
/**
* Return capability of the used RAM dataspace
*/
Ram_dataspace_capability cap() const { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at
* the caller. A newly allocated RAM dataspace is
* untyped memory anyway.
*/
template <typename T>
T *local_addr() const { return static_cast<T *>(_local_addr); }
/**
* Return size
*/
size_t size() const { return _size; }
void swap(Attached_ram_dataspace &other)
{
_swap(_size, other._size);
_swap(_ram, other._ram);
_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 = ram_session;
_alloc_and_attach();
}
};
#endif /* _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_ */

View File

@ -0,0 +1,124 @@
/*
* \brief Utility to open a ROM session and locally attach its content
* \author Norman Feske
* \date 2012-01-09
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_
#include <util/volatile_object.h>
#include <base/attached_dataspace.h>
#include <rom_session/connection.h>
namespace Genode { class Attached_rom_dataspace; }
class Genode::Attached_rom_dataspace
{
private:
Region_map &_rm;
Rom_connection _rom;
/*
* A ROM module may change or disappear over the lifetime of a ROM
* session. In contrast to the plain 'Attached_dataspace', which is
* always be valid once constructed, a 'Attached_rom_dataspace' has
* to handle the validity of the dataspace.
*/
Lazy_volatile_object<Attached_dataspace> _ds;
/**
* Try to attach the ROM module, ignore invalid dataspaces
*/
void _try_attach()
{
/*
* Normally, '_ds.construct()' would implicitly destruct an
* existing dataspace upon re-construction. However, we have to
* explicitly destruct the original dataspace prior calling
* '_rom.dataspace()'.
*
* The ROM server may destroy the original dataspace when the
* 'dataspace()' method is called. In this case, all existing
* mappings of the dataspace will be flushed by core. A destruction
* of 'Attached_dataspace' after this point will attempt to detach
* the already flushed mappings, thereby producing error messages
* at core.
*/
_ds.destruct();
try { _ds.construct(_rm, _rom.dataspace()); }
catch (Attached_dataspace::Invalid_dataspace) { }
}
public:
/**
* Constructor
*
* \throw Rom_connection::Rom_connection_failed
* \throw Rm_session::Attach_failed
*/
Attached_rom_dataspace(Env &env, char const *name)
: _rm(env.rm()), _rom(env, name) { _try_attach(); }
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with 'Env &' as first
* argument instead
*/
Attached_rom_dataspace(char const *name)
: _rm(*env()->rm_session()), _rom(name) { _try_attach(); }
/**
* Return capability of the used dataspace
*/
Dataspace_capability cap() const { return _ds->cap(); }
template <typename T> T *local_addr() { return _ds->local_addr<T>(); }
size_t size() const { return _ds->size(); }
/**
* Register signal handler for ROM module changes
*/
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
/**
* Update ROM module content, re-attach if needed
*/
void update()
{
/*
* If the dataspace is already attached and the update fits into
* the existing dataspace, we can keep everything in place. The
* dataspace content gets updated by the call of '_rom.update'.
*/
if (_ds.is_constructed() && _rom.update() == true)
return;
/*
* If there was no valid dataspace attached beforehand or the
* new data size exceeds the capacity of the existing dataspace,
* replace the current dataspace by a new one.
*/
_try_attach();
}
/**
* Return true of content is present
*/
bool is_valid() const { return _ds.is_constructed(); }
};
#endif /* _INCLUDE__BASE__ATTACHED_ROM_DATASPACE_H_ */

View File

@ -29,6 +29,22 @@ struct Genode::Io_mem_connection : Connection<Io_mem_session>, Io_mem_session_cl
* \param size size memory-mapped I/O resource
* \param write_combined enable write-combined access to I/O memory
*/
Io_mem_connection(Env &env, addr_t base, size_t size, bool write_combined = false)
:
Connection<Io_mem_session>(
session("ram_quota=4K, base=0x%p, size=0x%zx, wc=%s",
base, size, write_combined ? "yes" : "no")),
Io_mem_session_client(cap())
{ }
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with 'Env &' as first
* argument instead
*/
Io_mem_connection(addr_t base, size_t size, bool write_combined = false)
:
Connection<Io_mem_session>(

View File

@ -51,6 +51,19 @@ class Genode::Rom_connection : public Connection<Rom_session>,
*
* \throw Rom_connection_failed
*/
Rom_connection(Env &env, const char *module_name, const char *label = 0)
:
Connection<Rom_session>(_create_session(module_name, label)),
Rom_session_client(cap())
{ }
/**
* Constructor
*
* \noapi
* \deprecated Use the constructor with 'Env &' as first
* argument instead
*/
Rom_connection(const char *module_name, const char *label = 0)
:
Connection<Rom_session>(_create_session(module_name, label)),

View File

@ -2,6 +2,8 @@
* \brief Dataspace utility
* \author Norman Feske
* \date 2014-01-10
*
* \deprecated This header exists for API compatibility only.
*/
/*
@ -14,85 +16,6 @@
#ifndef _INCLUDE__OS__ATTACHED_DATASPACE_H_
#define _INCLUDE__OS__ATTACHED_DATASPACE_H_
#include <dataspace/client.h>
#include <base/env.h>
namespace Genode { class Attached_dataspace; }
class Genode::Attached_dataspace : Noncopyable
{
public:
/**
* Exception type
*/
class Invalid_dataspace { };
private:
Dataspace_capability _ds;
size_t const _size = { Dataspace_client(_ds).size() };
void *_local_addr = { env()->rm_session()->attach(_ds) };
Dataspace_capability _check(Dataspace_capability ds)
{
if (ds.valid())
return ds;
throw Invalid_dataspace();
}
public:
/**
* Constructor
*
* \throw Rm_session::Attach_failed
* \throw Invalid_dataspace
*/
Attached_dataspace(Dataspace_capability ds) : _ds(_check(ds)) { }
/**
* Destructor
*/
~Attached_dataspace()
{
if (_local_addr)
env()->rm_session()->detach(_local_addr);
}
/**
* Return capability of the used dataspace
*/
Dataspace_capability cap() const { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at the caller.
* A newly attached dataspace is untyped memory anyway.
*/
template <typename T>
T *local_addr() { return static_cast<T *>(_local_addr); }
/**
* Return size
*/
size_t size() const { return _size; }
/**
* Forget dataspace, thereby skipping the detachment on destruction
*
* This method can be called if the the dataspace is known to be
* physically destroyed, e.g., because the session where the dataspace
* originated from was closed. In this case, core will already have
* removed the memory mappings of the dataspace. So we have to omit the
* detach operation in '~Attached_dataspace'.
*/
void invalidate() { _local_addr = nullptr; }
};
#include <base/attached_dataspace.h>
#endif /* _INCLUDE__OS__ATTACHED_DATASPACE_H_ */

View File

@ -2,6 +2,8 @@
* \brief I/O MEM dataspace utility
* \author Norman Feske
* \date 2011-05-19
*
* \deprecated This header exists for API compatibility only.
*/
/*
@ -14,73 +16,6 @@
#ifndef _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_
#define _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_
#include <io_mem_session/connection.h>
#include <base/env.h>
namespace Genode { class Attached_io_mem_dataspace; }
/**
* Request and locally attach a memory-mapped I/O resource
*
* This class is a wrapper for a typical sequence of operations performed
* by device drivers to access memory-mapped device resources. Its sole
* purpose is to avoid duplicated code.
*/
class Genode::Attached_io_mem_dataspace
{
private:
Io_mem_connection _mmio;
Io_mem_dataspace_capability _ds;
void *_local_addr;
public:
/**
* Constructor
*
* \param base base address of memory-mapped I/O resource
* \param size size of resource
* \param write_combined enable write combining for the resource
*
* \throw Parent::Service_denied
* \throw Parent::Quota_exceeded
* \throw Parent::Unavailable
* \throw Rm_session::Attach_failed
*/
Attached_io_mem_dataspace(Genode::addr_t base, Genode::size_t size,
bool write_combined = false)
:
_mmio(base, size, write_combined),
_ds(_mmio.dataspace()),
_local_addr(env()->rm_session()->attach(_ds))
{
/* apply sub-page offset to virtual address */
_local_addr = (void *)((addr_t)_local_addr | (base & (addr_t)0xfff));
}
/**
* Destructor
*/
~Attached_io_mem_dataspace()
{
env()->rm_session()->detach(_local_addr);
}
/**
* Return capability of the used RAM dataspace
*/
Io_mem_dataspace_capability cap() { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at the caller.
* A newly allocated I/O MEM dataspace is untyped memory anyway.
*/
template <typename T>
T *local_addr() { return static_cast<T *>(_local_addr); }
};
#include <base/attached_io_mem_dataspace.h>
#endif /* _INCLUDE__OS__ATTACHED_IO_MEM_DATASPACE_H_ */

View File

@ -2,6 +2,8 @@
* \brief RAM dataspace utility
* \author Norman Feske
* \date 2008-03-22
*
* \deprecated This header exists for API compatibility only.
*/
/*
@ -14,142 +16,6 @@
#ifndef _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_
#define _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_
#include <ram_session/ram_session.h>
#include <util/touch.h>
#include <base/env.h>
namespace Genode { class Attached_ram_dataspace; }
/*
* Utility for allocating and attaching a RAM dataspace
*
* The combination of RAM allocation and a local RM attachment is a frequent
* use case. Each function may fail, which makes error handling inevitable.
* This utility class encapsulates this functionality to handle both operations
* as a transaction. When embedded as a member, this class also takes care
* about freeing and detaching the dataspace at destruction time.
*/
class Genode::Attached_ram_dataspace
{
private:
size_t _size;
Ram_session *_ram_session;
Ram_dataspace_capability _ds;
void *_local_addr;
Cache_attribute const _cached;
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, _cached);
_local_addr = env()->rm_session()->attach(_ds);
/* revert allocation if attaching the dataspace failed */
} catch (Rm_session::Attach_failed) {
_ram_session->free(_ds);
throw;
}
/*
* Eagerly map dataspace if used for DMA
*
* On some platforms, namely Fiasco.OC on ARMv7, the handling
* of page faults interferes with the caching attributes used
* for uncached DMA memory. See issue #452 for more details
* (https://github.com/genodelabs/genode/issues/452). As a
* work-around for this issues, we eagerly map the whole
* dataspace before writing actual content to it.
*/
if (_cached != CACHED) {
enum { PAGE_SIZE = 4096 };
unsigned char volatile *base = (unsigned char volatile *)_local_addr;
for (size_t i = 0; i < _size; i += PAGE_SIZE)
touch_read_write(base + i);
}
}
public:
/**
* Constructor
*
* \throw Ram_session::Alloc_failed
* \throw Rm_session::Attach_failed
*/
Attached_ram_dataspace(Ram_session *ram_session, size_t size,
Cache_attribute cached = CACHED)
:
_size(size), _ram_session(ram_session), _local_addr(0),
_cached(cached)
{
_alloc_and_attach();
}
/**
* Destructor
*/
~Attached_ram_dataspace() { _detach_and_free_dataspace(); }
/**
* Return capability of the used RAM dataspace
*/
Ram_dataspace_capability cap() const { return _ds; }
/**
* Request local address
*
* This is a template to avoid inconvenient casts at
* the caller. A newly allocated RAM dataspace is
* untyped memory anyway.
*/
template <typename T>
T *local_addr() const { return static_cast<T *>(_local_addr); }
/**
* 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();
}
};
#include <base/attached_ram_dataspace.h>
#endif /* _INCLUDE__OS__ATTACHED_RAM_DATASPACE_H_ */

View File

@ -2,6 +2,8 @@
* \brief ROM dataspace utility
* \author Norman Feske
* \date 2012-01-09
*
* \deprecated This header exists for API compatibility only.
*/
/*
@ -14,100 +16,6 @@
#ifndef _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_
#define _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_
#include <util/volatile_object.h>
#include <os/attached_dataspace.h>
#include <rom_session/connection.h>
namespace Genode { class Attached_rom_dataspace; }
class Genode::Attached_rom_dataspace
{
private:
Rom_connection _rom;
/*
* A ROM module may change or disappear over the lifetime of a ROM
* session. In contrast to the plain 'Attached_dataspace', which is
* always be valid once constructed, a 'Attached_rom_dataspace' has
* to handle the validity of the dataspace.
*/
Lazy_volatile_object<Attached_dataspace> _ds;
/**
* Try to attach the ROM module, ignore invalid dataspaces
*/
void _try_attach()
{
/*
* Normally, '_ds.construct()' would implicitly destruct an
* existing dataspace upon re-construction. However, we have to
* explicitly destruct the original dataspace prior calling
* '_rom.dataspace()'.
*
* The ROM server may destroy the original dataspace when the
* 'dataspace()' method is called. In this case, all existing
* mappings of the dataspace will be flushed by core. A destruction
* of 'Attached_dataspace' after this point will attempt to detach
* the already flushed mappings, thereby producing error messages
* at core.
*/
_ds.destruct();
try { _ds.construct(_rom.dataspace()); }
catch (Attached_dataspace::Invalid_dataspace) { }
}
public:
/**
* Constructor
*
* \throw Rom_connection::Rom_connection_failed
* \throw Rm_session::Attach_failed
*/
Attached_rom_dataspace(char const *name)
: _rom(name) { _try_attach(); }
/**
* Return capability of the used dataspace
*/
Dataspace_capability cap() const { return _ds->cap(); }
template <typename T> T *local_addr() { return _ds->local_addr<T>(); }
size_t size() const { return _ds->size(); }
/**
* Register signal handler for ROM module changes
*/
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
/**
* Update ROM module content, re-attach if needed
*/
void update()
{
/*
* If the dataspace is already attached and the update fits into
* the existing dataspace, we can keep everything in place. The
* dataspace content gets updated by the call of '_rom.update'.
*/
if (_ds.is_constructed() && _rom.update() == true)
return;
/*
* If there was no valid dataspace attached beforehand or the
* new data size exceeds the capacity of the existing dataspace,
* replace the current dataspace by a new one.
*/
_try_attach();
}
/**
* Return true of content is present
*/
bool is_valid() const { return _ds.is_constructed(); }
};
#include <base/attached_rom_dataspace.h>
#endif /* _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ */