mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
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
This commit is contained in:
parent
0605180a61
commit
17a6318ad6
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user