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; return num_bytes;
} }
void _write(size_t num_bytes) size_t _write(size_t num_bytes)
{ {
char *dst = _io_buffer.local_addr<char>(); char *dst = _io_buffer.local_addr<char>();
while (num_bytes) { size_t written_bytes;
size_t size = _driver.write(dst, num_bytes); for (written_bytes = 0; written_bytes < num_bytes; ) {
num_bytes -= size; written_bytes += _driver.write(dst + written_bytes,
dst += size; num_bytes - written_bytes);
} }
return written_bytes;
} }
Dataspace_capability _dataspace() { return _io_buffer.cap(); } 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -183,14 +183,22 @@ namespace Terminal {
return num_bytes; return num_bytes;
} }
void _write(Genode::size_t num_bytes) Genode::size_t _write(Genode::size_t num_bytes)
{ {
/* sanitize argument */ /* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size()); num_bytes = Genode::min(num_bytes, _io_buffer.size());
/* write data to descriptor */ /* 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"); Genode::error("write error, dropping data");
return 0;
}
return written_bytes;
} }
Genode::Dataspace_capability _dataspace() 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -433,14 +433,22 @@ namespace Terminal {
return num_bytes; return num_bytes;
} }
void _write(Genode::size_t num_bytes) Genode::size_t _write(Genode::size_t num_bytes)
{ {
/* sanitize argument */ /* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size()); num_bytes = Genode::min(num_bytes, _io_buffer.size());
/* write data to socket, assuming that it won't block */ /* 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"); Genode::error("write error, dropping data");
return 0;
}
return written_bytes;
} }
Genode::Dataspace_capability _dataspace() 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -427,7 +427,7 @@ namespace Terminal {
return num_bytes; return num_bytes;
} }
void _write(Genode::size_t num_bytes) Genode::size_t _write(Genode::size_t num_bytes)
{ {
Genode::Lock::Guard guard(_lock); Genode::Lock::Guard guard(_lock);
@ -439,6 +439,8 @@ namespace Terminal {
_decoder.insert(src[i]); _decoder.insert(src[i]);
} }
_trigger_flush_callback.trigger_flush(); _trigger_flush_callback.trigger_flush();
return num_bytes;
} }
Genode::Dataspace_capability _dataspace() 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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; 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>(); 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 */ /* submit character to sequence decoder */
_decoder.insert(src[i]); _decoder.insert(src[i]);
} }
return num_bytes;
} }
Genode::Dataspace_capability _dataspace() 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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) { while (written_bytes < num_bytes) {
/* copy payload to I/O buffer */ /* copy payload to I/O buffer */
Genode::size_t n = Genode::min(num_bytes - written_bytes, Genode::size_t payload_bytes = Genode::min(num_bytes - written_bytes,
_io_buffer.size()); _io_buffer.size());
Genode::memcpy(_io_buffer.local_addr<char>(), 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 */ /* 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) 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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_size, Size, size);
GENODE_RPC(Rpc_avail, bool, avail); GENODE_RPC(Rpc_avail, bool, avail);
GENODE_RPC(Rpc_read, Genode::size_t, _read, Genode::size_t); 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_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_read_avail_sigh, void, read_avail_sigh, Genode::Signal_context_capability);
GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, _dataspace); 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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; 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()); num_bytes = Genode::min(num_bytes, _io_buffer.size());
char const *io_buf = _io_buffer.local_addr<char>(); char const *io_buf = _io_buffer.local_addr<char>();
for (Genode::size_t i = 0; i < num_bytes; i++) for (Genode::size_t i = 0; i < num_bytes; i++)
_driver.put_char(io_buf[i]); _driver.put_char(io_buf[i]);
return num_bytes;
} }
Genode::Dataspace_capability _dataspace() { 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; } 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 */ /* sanitize argument */
num_bytes = Genode::min(num_bytes, _io_buffer.size()); num_bytes = Genode::min(num_bytes, _io_buffer.size());
char const *src = _io_buffer.local_addr<char>(); 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, written_bytes += _output.write(src + written_bytes,
num_bytes - written_bytes); num_bytes - written_bytes);
return written_bytes;
} }
Dataspace_capability _dataspace() { return _io_buffer.cap(); } 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>(); 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 num_bytes_written = 0;
size_t src_index = 0; size_t src_index = 0;
while (num_bytes_written < num_bytes) 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; _cross_num_bytes_avail += num_bytes_written;
_partner.cross_write(); _partner.cross_write();
return num_bytes_total;
} }

View File

@ -74,7 +74,7 @@ namespace Terminal {
Genode::size_t _read(Genode::size_t dst_len); 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(); Genode::Dataspace_capability _dataspace();