genode/repos/os/include/vfs/remote_io.h
Norman Feske 7d8d4f4532 vfs,libc: deferred wakeup of remote peers
This patch facilitates the batching of I/O operations in the VFS library
by replacing the implicit wakeup of remote peer (via the traditional
packet-stream interface like 'submit_packet') by explicit wakeup
signalling.

The wakeup signalling is triggered not before the VFS user settles down.
E.g., for libc-based applications, this is the case if the libc goes
idle, waiting for external I/O.
In the case of a busy writer to a non-blocking file descriptor or socket
(e.g., lighttpd), the remote peers are woken up once a write operation
yields an out-count of 0.

The deferring of wakeup signals is accommodated by the new 'Remote_io'
mechanism (vfs/remote_io.h) that is designated to be used by all VFS
plugins that interact with asynchronous Genode services for I/O.

Issue #4697
2023-01-24 12:07:27 +01:00

105 lines
1.9 KiB
C++

/*
* \brief Mechanism for waking up remote I/O peers
* \author Norman Feske
* \date 2022-12-01
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__VFS__REMOTE_IO_H_
#define _INCLUDE__VFS__REMOTE_IO_H_
#include <base/registry.h>
#include <vfs/types.h>
namespace Vfs { class Remote_io; }
struct Vfs::Remote_io : Interface
{
virtual void wakeup_remote_peer() = 0;
class Deferred_wakeups;
class Peer;
};
class Vfs::Remote_io::Peer : Genode::Noncopyable
{
private:
struct Deferred_wakeup;
using Wakeup_registry = Genode::Registry<Deferred_wakeup>;
class Deferred_wakeup : Wakeup_registry::Element, Interface
{
private:
Peer &_peer;
public:
Deferred_wakeup(Wakeup_registry &registry, Peer &peer)
:
Wakeup_registry::Element(registry, *this), _peer(peer)
{ }
void trigger() { _peer._wakeup(); }
};
friend class Deferred_wakeups;
Deferred_wakeups &_deferred_wakeups;
Remote_io &_remote_io;
Genode::Constructible<Deferred_wakeup> _deferred_wakeup { };
void _wakeup()
{
_remote_io.wakeup_remote_peer();
_deferred_wakeup.destruct();
}
public:
Peer(Deferred_wakeups &deferred_wakeups, Remote_io &remote_io)
:
_deferred_wakeups(deferred_wakeups), _remote_io(remote_io)
{ }
inline void schedule_wakeup();
};
class Vfs::Remote_io::Deferred_wakeups : Genode::Noncopyable
{
private:
Peer::Wakeup_registry _registry { };
friend class Peer;
public:
void trigger()
{
_registry.for_each([&] (Peer::Deferred_wakeup &deferred_wakeup) {
deferred_wakeup.trigger(); });
}
};
void Vfs::Remote_io::Peer::schedule_wakeup()
{
_deferred_wakeup.construct(_deferred_wakeups._registry, *this);
}
#endif /* _INCLUDE__VFS__REMOTE_IO_H_ */