terminal session: return number of bytes written

To better support non-blocking terminal components, let the
'Terminal::Session::write()' function return the number of bytes
actually written.

Fixes #2240
This commit is contained in:
Christian Prochaska 2017-01-17 15:45:54 +01:00 committed by Norman Feske
parent 9f7a4feab4
commit dbb641d44a
11 changed files with 65 additions and 31 deletions

View File

@ -277,14 +277,15 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
return num_bytes;
}
void _write(size_t num_bytes)
size_t _write(size_t num_bytes)
{
char *dst = _io_buffer.local_addr<char>();
while (num_bytes) {
size_t size = _driver.write(dst, num_bytes);
num_bytes -= size;
dst += size;
size_t written_bytes;
for (written_bytes = 0; written_bytes < num_bytes; ) {
written_bytes += _driver.write(dst + written_bytes,
num_bytes - written_bytes);
}
return written_bytes;
}
Dataspace_capability _dataspace() { return _io_buffer.cap(); }

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2017 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.
@ -183,14 +183,22 @@ namespace Terminal {
return num_bytes;
}
void _write(Genode::size_t num_bytes)
Genode::size_t _write(Genode::size_t num_bytes)
{
/* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size());
/* write data to descriptor */
if (::write(fd(), _io_buffer.local_addr<char>(), num_bytes) < 0)
ssize_t written_bytes = ::write(fd(),
_io_buffer.local_addr<char>(),
num_bytes);
if (written_bytes < 0) {
Genode::error("write error, dropping data");
return 0;
}
return written_bytes;
}
Genode::Dataspace_capability _dataspace()

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2016 Genode Labs GmbH
* Copyright (C) 2011-2017 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.
@ -433,14 +433,22 @@ namespace Terminal {
return num_bytes;
}
void _write(Genode::size_t num_bytes)
Genode::size_t _write(Genode::size_t num_bytes)
{
/* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size());
/* write data to socket, assuming that it won't block */
if (::write(sd(), _io_buffer.local_addr<char>(), num_bytes) < 0)
ssize_t written_bytes = ::write(sd(),
_io_buffer.local_addr<char>(),
num_bytes);
if (written_bytes < 0) {
Genode::error("write error, dropping data");
return 0;
}
return written_bytes;
}
Genode::Dataspace_capability _dataspace()

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2011-2017 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.
@ -427,7 +427,7 @@ namespace Terminal {
return num_bytes;
}
void _write(Genode::size_t num_bytes)
Genode::size_t _write(Genode::size_t num_bytes)
{
Genode::Lock::Guard guard(_lock);
@ -439,6 +439,8 @@ namespace Terminal {
_decoder.insert(src[i]);
}
_trigger_flush_callback.trigger_flush();
return num_bytes;
}
Genode::Dataspace_capability _dataspace()

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2017 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.
@ -297,7 +297,7 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
return num_bytes;
}
void _write(Genode::size_t num_bytes)
Genode::size_t _write(Genode::size_t num_bytes)
{
unsigned char *src = _io_buffer.local_addr<unsigned char>();
@ -306,6 +306,8 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
/* submit character to sequence decoder */
_decoder.insert(src[i]);
}
return num_bytes;
}
Genode::Dataspace_capability _dataspace()

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2011-2017 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.
@ -80,17 +80,21 @@ class Terminal::Session_client : public Genode::Rpc_client<Session>
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::size_t payload_bytes = Genode::min(num_bytes - written_bytes,
_io_buffer.size());
Genode::memcpy(_io_buffer.local_addr<char>(),
src + written_bytes, n);
src + written_bytes, payload_bytes);
/* tell server to pick up new I/O buffer content */
call<Rpc_write>(n);
Genode::size_t written_payload_bytes = call<Rpc_write>(payload_bytes);
written_bytes += written_payload_bytes;
if (written_payload_bytes != payload_bytes)
return written_bytes;
written_bytes += n;
}
return num_bytes;
return written_bytes;
}
void connected_sigh(Genode::Signal_context_capability cap)

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2011-2017 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.
@ -91,7 +91,7 @@ struct Terminal::Session : Genode::Session
GENODE_RPC(Rpc_size, Size, size);
GENODE_RPC(Rpc_avail, bool, avail);
GENODE_RPC(Rpc_read, Genode::size_t, _read, Genode::size_t);
GENODE_RPC(Rpc_write, void, _write, Genode::size_t);
GENODE_RPC(Rpc_write, Genode::size_t, _write, Genode::size_t);
GENODE_RPC(Rpc_connected_sigh, void, connected_sigh, Genode::Signal_context_capability);
GENODE_RPC(Rpc_read_avail_sigh, void, read_avail_sigh, Genode::Signal_context_capability);
GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, _dataspace);

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2011-2016 Genode Labs GmbH
* Copyright (C) 2011-2017 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.
@ -168,14 +168,16 @@ class Uart::Session_component : public Rpc_object<Uart::Session,
return n;
}
void _write(Genode::size_t num_bytes)
Genode::size_t _write(Genode::size_t num_bytes)
{
/* constain argument to I/O buffer size */
/* constrain argument to I/O buffer size */
num_bytes = Genode::min(num_bytes, _io_buffer.size());
char const *io_buf = _io_buffer.local_addr<char>();
for (Genode::size_t i = 0; i < num_bytes; i++)
_driver.put_char(io_buf[i]);
return num_bytes;
}
Genode::Dataspace_capability _dataspace() {

View File

@ -117,16 +117,19 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
size_t _read(size_t dst_len) { return 0; }
void _write(Genode::size_t num_bytes)
size_t _write(Genode::size_t num_bytes)
{
/* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size());
char const *src = _io_buffer.local_addr<char>();
for (size_t written_bytes = 0; written_bytes < num_bytes; )
size_t written_bytes;
for (written_bytes = 0; written_bytes < num_bytes; )
written_bytes += _output.write(src + written_bytes,
num_bytes - written_bytes);
return written_bytes;
}
Dataspace_capability _dataspace() { return _io_buffer.cap(); }

View File

@ -92,10 +92,12 @@ Genode::size_t Session_component::_read(Genode::size_t dst_len)
}
void Session_component::_write(Genode::size_t num_bytes)
Genode::size_t Session_component::_write(Genode::size_t num_bytes)
{
unsigned char *src = _io_buffer.local_addr<unsigned char>();
size_t const num_bytes_total = num_bytes;
size_t num_bytes_written = 0;
size_t src_index = 0;
while (num_bytes_written < num_bytes)
@ -129,6 +131,8 @@ void Session_component::_write(Genode::size_t num_bytes)
_cross_num_bytes_avail += num_bytes_written;
_partner.cross_write();
return num_bytes_total;
}

View File

@ -74,7 +74,7 @@ namespace Terminal {
Genode::size_t _read(Genode::size_t dst_len);
void _write(Genode::size_t num_bytes);
Genode::size_t _write(Genode::size_t num_bytes);
Genode::Dataspace_capability _dataspace();