mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-14 22:47:12 +00:00
New 'os/attached_dataspace.h' utility
The new Attached_dataspace complements the existing Attached_* utilities with a simple version that can be used with any kind of dataspaces. It may be even useful as a common base type for the other variants. For example, this patch simplifies Attached_rom_dataspace and removes the Terminal::Client::Io_buffer.
This commit is contained in:
parent
759e11f9af
commit
bdfbe9f20e
os/include
83
os/include/os/attached_dataspace.h
Normal file
83
os/include/os/attached_dataspace.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* \brief Dataspace utility
|
||||
* \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__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 * const _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() { 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; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_DATASPACE_H_ */
|
@ -14,93 +14,65 @@
|
||||
#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>
|
||||
#include <dataspace/client.h>
|
||||
#include <base/env.h>
|
||||
|
||||
namespace Genode {
|
||||
namespace Genode { class Attached_rom_dataspace; }
|
||||
|
||||
class Attached_rom_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Rom_connection _rom;
|
||||
Rom_dataspace_capability _ds;
|
||||
size_t _size;
|
||||
void *_local_addr = 0;
|
||||
class Genode::Attached_rom_dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
void _detach()
|
||||
{
|
||||
if (!_local_addr)
|
||||
return;
|
||||
Rom_connection _rom;
|
||||
|
||||
env()->rm_session()->detach(_local_addr);
|
||||
_local_addr = 0;
|
||||
_size = 0;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
void _attach()
|
||||
{
|
||||
if (_local_addr)
|
||||
_detach();
|
||||
/**
|
||||
* Try to attach the ROM module, ignore invalid dataspaces
|
||||
*/
|
||||
void _try_attach()
|
||||
{
|
||||
try { _ds.construct(_rom.dataspace()); }
|
||||
catch (Attached_dataspace::Invalid_dataspace) { }
|
||||
}
|
||||
|
||||
_ds = _rom.dataspace();
|
||||
if (_ds.valid()) {
|
||||
_size = Dataspace_client(_ds).size();
|
||||
_local_addr = env()->rm_session()->attach(_ds);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rom_connection::Rom_connection_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_rom_dataspace(char const *name)
|
||||
: _rom(name) { _try_attach(); }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Rom_connection::Rom_connection_failed
|
||||
* \throw Rm_session::Attach_failed
|
||||
*/
|
||||
Attached_rom_dataspace(char const *name)
|
||||
: _rom(name) { _attach(); }
|
||||
template <typename T> T *local_addr() { return _ds->local_addr<T>(); }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Attached_rom_dataspace() { _detach(); }
|
||||
size_t size() const { return _ds->size(); }
|
||||
|
||||
/**
|
||||
* Return capability of the used ROM dataspace
|
||||
*/
|
||||
Rom_dataspace_capability cap() const { return _ds; }
|
||||
/**
|
||||
* Register signal handler for ROM module changes
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
|
||||
|
||||
/**
|
||||
* Request local address
|
||||
*
|
||||
* This is a template to avoid inconvenient casts at the caller.
|
||||
* A newly allocated ROM dataspace is untyped memory anyway.
|
||||
*/
|
||||
template <typename T>
|
||||
T *local_addr() { return static_cast<T *>(_local_addr); }
|
||||
/**
|
||||
* Re-attach ROM module
|
||||
*/
|
||||
void update() { _try_attach(); }
|
||||
|
||||
/**
|
||||
* Return size
|
||||
*/
|
||||
size_t size() const { return _size; }
|
||||
|
||||
/**
|
||||
* Register signal handler for ROM module changes
|
||||
*/
|
||||
void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); }
|
||||
|
||||
/**
|
||||
* Re-attach ROM module
|
||||
*/
|
||||
void update() { _attach(); }
|
||||
|
||||
/**
|
||||
* Return true of content is present
|
||||
*/
|
||||
bool is_valid() const { return _local_addr != 0; }
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Return true of content is present
|
||||
*/
|
||||
bool is_valid() const { return _ds.is_constructed(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ */
|
||||
|
@ -18,103 +18,86 @@
|
||||
#include <util/misc_math.h>
|
||||
#include <util/string.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/env.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <os/attached_dataspace.h>
|
||||
|
||||
#include <terminal_session/terminal_session.h>
|
||||
|
||||
namespace Terminal {
|
||||
namespace Terminal { class Session_client; }
|
||||
|
||||
class Session_client : public Genode::Rpc_client<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Shared-memory buffer used for carrying the payload
|
||||
* of read/write operations
|
||||
*/
|
||||
struct Io_buffer
|
||||
{
|
||||
Genode::Dataspace_capability ds_cap;
|
||||
char *base;
|
||||
Genode::size_t size;
|
||||
Genode::Lock lock;
|
||||
class Terminal::Session_client : public Genode::Rpc_client<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Io_buffer(Genode::Dataspace_capability ds_cap)
|
||||
:
|
||||
ds_cap(ds_cap),
|
||||
base(Genode::env()->rm_session()->attach(ds_cap)),
|
||||
size(ds_cap.call<Genode::Dataspace::Rpc_size>())
|
||||
{ }
|
||||
Genode::Lock _lock;
|
||||
|
||||
~Io_buffer()
|
||||
{
|
||||
Genode::env()->rm_session()->detach(base);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Shared-memory buffer used for carrying the payload
|
||||
* of read/write operations
|
||||
*/
|
||||
Genode::Attached_dataspace _io_buffer;
|
||||
|
||||
Io_buffer _io_buffer;
|
||||
public:
|
||||
|
||||
public:
|
||||
Session_client(Genode::Capability<Session> cap)
|
||||
:
|
||||
Genode::Rpc_client<Session>(cap),
|
||||
_io_buffer(call<Rpc_dataspace>())
|
||||
{ }
|
||||
|
||||
Session_client(Genode::Capability<Session> cap)
|
||||
:
|
||||
Genode::Rpc_client<Session>(cap),
|
||||
_io_buffer(call<Rpc_dataspace>())
|
||||
{ }
|
||||
Size size() { return call<Rpc_size>(); }
|
||||
|
||||
Size size() { return call<Rpc_size>(); }
|
||||
bool avail() { return call<Rpc_avail>(); }
|
||||
|
||||
bool avail() { return call<Rpc_avail>(); }
|
||||
Genode::size_t read(void *buf, Genode::size_t buf_size)
|
||||
{
|
||||
Genode::Lock::Guard _guard(_lock);
|
||||
|
||||
Genode::size_t read(void *buf, Genode::size_t buf_size)
|
||||
{
|
||||
Genode::Lock::Guard _guard(_io_buffer.lock);
|
||||
/* instruct server to fill the I/O buffer */
|
||||
Genode::size_t num_bytes = call<Rpc_read>(buf_size);
|
||||
|
||||
/* instruct server to fill the I/O buffer */
|
||||
Genode::size_t num_bytes = call<Rpc_read>(buf_size);
|
||||
/* copy-out I/O buffer */
|
||||
num_bytes = Genode::min(num_bytes, buf_size);
|
||||
Genode::memcpy(buf, _io_buffer.local_addr<char>(), num_bytes);
|
||||
|
||||
/* copy-out I/O buffer */
|
||||
num_bytes = Genode::min(num_bytes, buf_size);
|
||||
Genode::memcpy(buf, _io_buffer.base, num_bytes);
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
return num_bytes;
|
||||
Genode::size_t write(void const *buf, Genode::size_t num_bytes)
|
||||
{
|
||||
Genode::Lock::Guard _guard(_lock);
|
||||
|
||||
Genode::size_t written_bytes = 0;
|
||||
char const * const src = (char const *)buf;
|
||||
|
||||
while (written_bytes < num_bytes) {
|
||||
|
||||
/* copy payload to I/O buffer */
|
||||
Genode::size_t n = Genode::min(num_bytes - written_bytes,
|
||||
_io_buffer.size());
|
||||
Genode::memcpy(_io_buffer.local_addr<char>(),
|
||||
src + written_bytes, n);
|
||||
|
||||
/* tell server to pick up new I/O buffer content */
|
||||
call<Rpc_write>(n);
|
||||
|
||||
written_bytes += n;
|
||||
}
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
Genode::size_t write(void const *buf, Genode::size_t num_bytes)
|
||||
{
|
||||
Genode::Lock::Guard _guard(_io_buffer.lock);
|
||||
void connected_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
call<Rpc_connected_sigh>(cap);
|
||||
}
|
||||
|
||||
Genode::size_t written_bytes = 0;
|
||||
char const * const src = (char const *)buf;
|
||||
void read_avail_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
call<Rpc_read_avail_sigh>(cap);
|
||||
}
|
||||
|
||||
while (written_bytes < num_bytes) {
|
||||
|
||||
/* copy payload to I/O buffer */
|
||||
Genode::size_t n = Genode::min(num_bytes - written_bytes,
|
||||
_io_buffer.size);
|
||||
Genode::memcpy(_io_buffer.base, src + written_bytes, n);
|
||||
|
||||
/* tell server to pick up new I/O buffer content */
|
||||
call<Rpc_write>(n);
|
||||
|
||||
written_bytes += n;
|
||||
}
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
call<Rpc_connected_sigh>(cap);
|
||||
}
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability cap)
|
||||
{
|
||||
call<Rpc_read_avail_sigh>(cap);
|
||||
}
|
||||
|
||||
Genode::size_t io_buffer_size() const { return _io_buffer.size; }
|
||||
};
|
||||
}
|
||||
Genode::size_t io_buffer_size() const { return _io_buffer.size(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__TERMINAL_SESSION__CLIENT_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user