From dbb641d44a4bd2a1932b7d4b116706f31d4c0dc5 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 17 Jan 2017 15:45:54 +0100 Subject: [PATCH] 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 --- .../dde_linux/src/server/usb_terminal/main.cc | 11 ++++++----- repos/gems/src/server/file_terminal/main.cc | 14 +++++++++++--- repos/gems/src/server/tcp_terminal/main.cc | 14 +++++++++++--- repos/gems/src/server/terminal/main.cc | 6 ++++-- repos/gems/src/server/terminal_mux/main.cc | 6 ++++-- repos/os/include/terminal_session/client.h | 18 +++++++++++------- .../terminal_session/terminal_session.h | 4 ++-- repos/os/src/drivers/uart/uart_component.h | 8 +++++--- repos/os/src/server/log_terminal/main.cc | 7 +++++-- .../terminal_session_component.cc | 6 +++++- .../terminal_session_component.h | 2 +- 11 files changed, 65 insertions(+), 31 deletions(-) diff --git a/repos/dde_linux/src/server/usb_terminal/main.cc b/repos/dde_linux/src/server/usb_terminal/main.cc index 4da34fc44..8a9f6e66c 100644 --- a/repos/dde_linux/src/server/usb_terminal/main.cc +++ b/repos/dde_linux/src/server/usb_terminal/main.cc @@ -277,14 +277,15 @@ class Terminal::Session_component : public Rpc_object(); - 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(); } diff --git a/repos/gems/src/server/file_terminal/main.cc b/repos/gems/src/server/file_terminal/main.cc index 9d68ced71..a29bc0431 100644 --- a/repos/gems/src/server/file_terminal/main.cc +++ b/repos/gems/src/server/file_terminal/main.cc @@ -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(), num_bytes) < 0) + ssize_t written_bytes = ::write(fd(), + _io_buffer.local_addr(), + num_bytes); + + if (written_bytes < 0) { Genode::error("write error, dropping data"); + return 0; + } + + return written_bytes; } Genode::Dataspace_capability _dataspace() diff --git a/repos/gems/src/server/tcp_terminal/main.cc b/repos/gems/src/server/tcp_terminal/main.cc index 9d4167a07..876f67dfe 100644 --- a/repos/gems/src/server/tcp_terminal/main.cc +++ b/repos/gems/src/server/tcp_terminal/main.cc @@ -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(), num_bytes) < 0) + ssize_t written_bytes = ::write(sd(), + _io_buffer.local_addr(), + num_bytes); + + if (written_bytes < 0) { Genode::error("write error, dropping data"); + return 0; + } + + return written_bytes; } Genode::Dataspace_capability _dataspace() diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index d7ba71be2..3a184ccf4 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -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() diff --git a/repos/gems/src/server/terminal_mux/main.cc b/repos/gems/src/server/terminal_mux/main.cc index 4c0787a22..f05ec8b2f 100644 --- a/repos/gems/src/server/terminal_mux/main.cc +++ b/repos/gems/src/server/terminal_mux/main.cc @@ -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(); @@ -306,6 +306,8 @@ class Terminal::Session_component : public Genode::Rpc_object 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(), - src + written_bytes, n); + src + written_bytes, payload_bytes); /* tell server to pick up new I/O buffer content */ - call(n); + Genode::size_t written_payload_bytes = call(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) diff --git a/repos/os/include/terminal_session/terminal_session.h b/repos/os/include/terminal_session/terminal_session.h index 2f901f5d5..c7abf0e96 100644 --- a/repos/os/include/terminal_session/terminal_session.h +++ b/repos/os/include/terminal_session/terminal_session.h @@ -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); diff --git a/repos/os/src/drivers/uart/uart_component.h b/repos/os/src/drivers/uart/uart_component.h index b6ffcf7f1..4dc247b5d 100644 --- a/repos/os/src/drivers/uart/uart_component.h +++ b/repos/os/src/drivers/uart/uart_component.h @@ -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(); for (Genode::size_t i = 0; i < num_bytes; i++) _driver.put_char(io_buf[i]); + + return num_bytes; } Genode::Dataspace_capability _dataspace() { diff --git a/repos/os/src/server/log_terminal/main.cc b/repos/os/src/server/log_terminal/main.cc index 16bcf300f..3005d583b 100644 --- a/repos/os/src/server/log_terminal/main.cc +++ b/repos/os/src/server/log_terminal/main.cc @@ -117,16 +117,19 @@ class Terminal::Session_component : public Rpc_object(); - 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(); } diff --git a/repos/os/src/server/terminal_crosslink/terminal_session_component.cc b/repos/os/src/server/terminal_crosslink/terminal_session_component.cc index af0d7c65d..4f1b210c2 100644 --- a/repos/os/src/server/terminal_crosslink/terminal_session_component.cc +++ b/repos/os/src/server/terminal_crosslink/terminal_session_component.cc @@ -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(); + 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; } diff --git a/repos/os/src/server/terminal_crosslink/terminal_session_component.h b/repos/os/src/server/terminal_crosslink/terminal_session_component.h index 4394adf91..acd32caec 100644 --- a/repos/os/src/server/terminal_crosslink/terminal_session_component.h +++ b/repos/os/src/server/terminal_crosslink/terminal_session_component.h @@ -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();