mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
32cb245cb8
commit
011a521968
@ -30,6 +30,7 @@
|
||||
<start name="terminal_crosslink">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Terminal"/> </provides>
|
||||
<config buffer="4K"/>
|
||||
</start>
|
||||
<start name="test-terminal_crosslink">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
|
@ -1,14 +1,11 @@
|
||||
The 'terminal_crosslink' server allows exactly two clients to communicate with
|
||||
each other using the 'Terminal' interface. Data sent to the server gets stored
|
||||
in a buffer of 4096 bytes (one buffer per client). As long as the data to be
|
||||
written fits into the buffer, the 'write()' call returns immediately. If no
|
||||
more data fits into the buffer, the 'write()' call blocks until the other
|
||||
client has consumed some of the data from the buffer via the 'read()' call. The
|
||||
'read()' call never blocks. A signal receiver can be used to block until new
|
||||
data is ready for reading.
|
||||
in a buffer of configurable size (one buffer per client, 4K by default). The
|
||||
'read()' and 'write()' calls never block. A signal receiver can be used to
|
||||
block until new data is ready for reading.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
An example run script 'terminal_crosslink.run' can be found in the 'os/run'
|
||||
directory.
|
||||
An example depot package 'test-terminal_crosslink' can be found in the
|
||||
'os/recipes/pkg' directory.
|
||||
|
@ -5,13 +5,14 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
|
||||
@ -27,10 +28,18 @@ namespace Terminal_crosslink {
|
||||
|
||||
struct Terminal_crosslink::Main
|
||||
{
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Env &_env;
|
||||
|
||||
Root _terminal_root { _env, _heap };
|
||||
Sliced_heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
Number_of_bytes const DEFAULT_BUFFER_SIZE { 4096 };
|
||||
|
||||
size_t const _buffer_size {
|
||||
_config.xml().attribute_value("buffer", DEFAULT_BUFFER_SIZE) };
|
||||
|
||||
Root _terminal_root { _env, _heap, _buffer_size };
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -67,10 +67,10 @@ namespace Terminal_crosslink {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Root(Env &env, Allocator &alloc)
|
||||
Root(Env &env, Allocator &alloc, size_t buffer_size)
|
||||
: Root_component(&env.ep().rpc_ep(), &alloc),
|
||||
_session_component1(env, _session_component2),
|
||||
_session_component2(env, _session_component1),
|
||||
_session_component1(env, _session_component2, buffer_size),
|
||||
_session_component2(env, _session_component1, buffer_size),
|
||||
_session_state(0)
|
||||
{ }
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -23,11 +23,13 @@
|
||||
using namespace Genode;
|
||||
|
||||
Terminal_crosslink::Session_component::Session_component(Env &env,
|
||||
Session_component &partner)
|
||||
Session_component &partner,
|
||||
size_t buffer_size)
|
||||
: _env(env),
|
||||
_partner(partner),
|
||||
_buffer_size(buffer_size),
|
||||
_session_cap(_env.ep().rpc_ep().manage(this)),
|
||||
_io_buffer(env.ram(), env.rm(), BUFFER_SIZE),
|
||||
_io_buffer(env.ram(), env.rm(), IO_BUFFER_SIZE),
|
||||
_cross_num_bytes_avail(0)
|
||||
{
|
||||
}
|
||||
@ -85,22 +87,25 @@ bool Terminal_crosslink::Session_component::avail()
|
||||
|
||||
size_t Terminal_crosslink::Session_component::_read(size_t dst_len)
|
||||
{
|
||||
return _partner.cross_read(_io_buffer.local_addr<unsigned char>(), dst_len);
|
||||
return _partner.cross_read(_io_buffer.local_addr<unsigned char>(),
|
||||
min(dst_len, _io_buffer.size()));
|
||||
}
|
||||
|
||||
|
||||
size_t Terminal_crosslink::Session_component::_write(size_t num_bytes)
|
||||
{
|
||||
num_bytes = min(num_bytes, _io_buffer.size());
|
||||
|
||||
unsigned char *src = _io_buffer.local_addr<unsigned char>();
|
||||
|
||||
size_t num_bytes_written = 0;
|
||||
while (num_bytes_written < num_bytes)
|
||||
try {
|
||||
_buffer.add(src[num_bytes_written]);
|
||||
++num_bytes_written;
|
||||
} catch(Local_buffer::Overflow) {
|
||||
break;
|
||||
}
|
||||
bool error = false;
|
||||
|
||||
while ((num_bytes_written < num_bytes) && !error)
|
||||
_buffer.add(src[num_bytes_written]).with_result(
|
||||
[&] (Ring_buffer::Add_ok) { ++num_bytes_written; },
|
||||
[&] (Ring_buffer::Add_error) { error = true; }
|
||||
);
|
||||
|
||||
_cross_num_bytes_avail += num_bytes_written;
|
||||
_partner.cross_write();
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2024 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -15,17 +15,113 @@
|
||||
#define _TERMINAL_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/heap.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <os/ring_buffer.h>
|
||||
#include <terminal_session/terminal_session.h>
|
||||
|
||||
namespace Terminal_crosslink {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = sizeof(addr_t)*1024 };
|
||||
enum { BUFFER_SIZE = 4096 };
|
||||
static constexpr size_t IO_BUFFER_SIZE = 4096;
|
||||
|
||||
class Ring_buffer
|
||||
{
|
||||
private:
|
||||
|
||||
size_t _head = 0;
|
||||
size_t _tail = 0;
|
||||
|
||||
char *_queue { };
|
||||
|
||||
size_t _queue_size;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Ring_buffer(Ring_buffer const &);
|
||||
Ring_buffer &operator = (Ring_buffer const &);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Ring_buffer(Byte_range_ptr const &buffer)
|
||||
: _queue(buffer.start), _queue_size(buffer.num_bytes) { }
|
||||
|
||||
struct Add_ok { };
|
||||
enum class Add_error { OVERFLOW };
|
||||
|
||||
using Add_result = Attempt<Add_ok, Add_error>;
|
||||
|
||||
/**
|
||||
* Place element into ring buffer
|
||||
*/
|
||||
Add_result add(char ev)
|
||||
{
|
||||
if ((_head + 1)%_queue_size != _tail) {
|
||||
_queue[_head] = ev;
|
||||
_head = (_head + 1)%_queue_size;
|
||||
return Add_ok();
|
||||
} else
|
||||
return Add_error::OVERFLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take element from ring buffer
|
||||
*
|
||||
* \return element
|
||||
*/
|
||||
char get()
|
||||
{
|
||||
unsigned char e = _queue[_tail];
|
||||
_tail = (_tail + 1)%_queue_size;
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if ring buffer is empty
|
||||
*/
|
||||
bool empty() const { return _tail == _head; }
|
||||
};
|
||||
|
||||
|
||||
class Allocated_ring_buffer : public Ring_buffer
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
char *_buffer { };
|
||||
|
||||
char *_init_buffer(Genode::Allocator &alloc, size_t size)
|
||||
{
|
||||
_buffer = static_cast<char*>(alloc.alloc(size));
|
||||
return _buffer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Allocated_ring_buffer(Allocated_ring_buffer const &);
|
||||
Allocated_ring_buffer &operator = (Allocated_ring_buffer const &);
|
||||
|
||||
public:
|
||||
|
||||
Allocated_ring_buffer(Genode::Allocator &alloc, size_t queue_size)
|
||||
: Ring_buffer(Byte_range_ptr(_init_buffer(alloc, queue_size),
|
||||
queue_size)),
|
||||
_alloc(alloc)
|
||||
{ }
|
||||
|
||||
~Allocated_ring_buffer()
|
||||
{
|
||||
destroy(_alloc, _buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Session_component : public Rpc_object<Terminal::Session,
|
||||
Session_component>
|
||||
@ -33,15 +129,17 @@ namespace Terminal_crosslink {
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Heap _alloc { _env.ram(), _env.rm() };
|
||||
|
||||
Session_component &_partner;
|
||||
|
||||
size_t _buffer_size;
|
||||
|
||||
Genode::Session_capability _session_cap;
|
||||
|
||||
Attached_ram_dataspace _io_buffer;
|
||||
|
||||
typedef Genode::Ring_buffer<unsigned char, BUFFER_SIZE+1> Local_buffer;
|
||||
|
||||
Local_buffer _buffer { };
|
||||
Allocated_ring_buffer _buffer { _alloc, _buffer_size + 1 };
|
||||
size_t _cross_num_bytes_avail;
|
||||
Signal_context_capability _read_avail_sigh { };
|
||||
|
||||
@ -50,7 +148,8 @@ namespace Terminal_crosslink {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Env &env, Session_component &partner);
|
||||
Session_component(Env &env, Session_component &partner,
|
||||
size_t buffer_size);
|
||||
|
||||
Session_capability cap();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user