From 17a6318ad68092f604223c4077564352c0721ff3 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 1 Sep 2020 18:19:58 +0200 Subject: [PATCH] vfs: process all acks in each iteration This patch solves a corner case where one long-active job (e.g., read-ready request) stays at the beginning of the '_active_jobs' queue without an ack. In this case, the '_try_acknowledge_jobs' method would wrongly stop processing the subsequent acknowledgements. In practice, this can lead to a delayed sending of acknowledgements until new I/O or client requests occur. In particular, Vim in Sculpt's inspect window sometimes did not immediately respond to key presses during tab completion. Here, the read-ready request of the terminal prevented the acknowledgement for read of directory entry from being delivered until the next key was pressed. Fixes #3873 --- repos/os/src/server/vfs/main.cc | 56 ++++++++++++++------------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/repos/os/src/server/vfs/main.cc b/repos/os/src/server/vfs/main.cc index c8a527d58a..723ddbc287 100644 --- a/repos/os/src/server/vfs/main.cc +++ b/repos/os/src/server/vfs/main.cc @@ -261,46 +261,36 @@ class Vfs_server::Session_component : private Session_resources, bool _try_acknowledge_jobs() { - bool overall_progress = false; + bool progress = false; - for (;;) { - if (!_stream.ready_to_ack()) - break; + Node_queue requeued_nodes { }; - if (_active_nodes.empty()) - break; + _active_nodes.dequeue_all([&] (Node &node) { - bool progress_in_iteration = false; + if (!_stream.ready_to_ack()) { + requeued_nodes.enqueue(node); + return; + } - _active_nodes.dequeue([&] (Node &node) { + if (node.acknowledgement_pending()) { + _stream.acknowledge_packet(node.dequeue_acknowledgement()); + progress = true; + } - /* - * Deliver only one acknowledgement per iteration to - * re-check the 'ready_to_ack' condition for each - * acknowledgement. - */ - if (node.acknowledgement_pending()) { - _stream.acknowledge_packet(node.dequeue_acknowledgement()); - progress_in_iteration = true; - } + /* + * If there is still another acknowledgement pending, + * keep the node enqueud to process it in the next call of + * '_try_acknowledge_jobs'. This can happen if there is a + * READ_READY acknowledgement in addition to the + * acknowledgement of an operation. + */ + if (node.active()) + requeued_nodes.enqueue(node); + }); - /* - * If there is still another acknowledgement pending, keep - * the node enqueud to process it in the next iteration. - * This can happen if there is a READ_READY acknowledgement - * in addition to the acknowledgement of an operation. - */ - if (node.active()) - _active_nodes.enqueue(node); - }); + _active_nodes = requeued_nodes; - overall_progress |= progress_in_iteration; - - if (!progress_in_iteration) - break; - } - - return overall_progress; + return progress; } public: