mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-23 17:17:38 +00:00
New VFS plugin for emulating POSIX pipes
Add a new plugin for creating pipes between pairs of VFS handles. It is intended to replace the libc_pipe plugin, one of the last remaining libc plugins. In contrast to the libc_pipe plugin, this plugin defers cross-handle notification until I/O signal handling rather than block and unblock readers using a semaphore. This is a performance regression in the case of multiple threads blocking on a pipe, but shall be an intermediate mechanism pending renovations within the libc VFS and threading layers. As a side effect, threads blocked on a pipe might not be resumed until the main thread suspends and dispatches I/O signals. The "test-libc_pipe" test has been adjusted to use the VFS pipe plugin and tests both local pipes and pipes hosted remotely in the VFS server. Merge adaptations (such as EOF handling, adjustment to VFS/libc interface changes) by Norman Feske. Fix #2303
This commit is contained in:
committed by
Christian Helmuth
parent
9b7915facb
commit
c51b4b5742
@ -2,4 +2,6 @@ _/src/init
|
||||
_/src/test-libc_pipe
|
||||
_/src/libc
|
||||
_/src/vfs
|
||||
_/src/vfs_pipe
|
||||
_/src/posix
|
||||
_/src/sequence
|
||||
|
@ -2,40 +2,71 @@
|
||||
|
||||
<events>
|
||||
<timeout meaning="failed" sec="30" />
|
||||
<log meaning="succeeded">child "test-libc_pipe" exited with exit value 0</log>
|
||||
<log meaning="succeeded">child "sequence" exited with exit value 0</log>
|
||||
<log meaning="failed">Error: </log>
|
||||
</events>
|
||||
|
||||
<content>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="libc.lib.so"/>
|
||||
<rom label="vfs.lib.so"/>
|
||||
<rom label="libm.lib.so"/>
|
||||
<rom label="libc_pipe.lib.so"/>
|
||||
<rom label="posix.lib.so"/>
|
||||
<rom label="sequence"/>
|
||||
<rom label="test-libc_pipe"/>
|
||||
<rom label="vfs"/>
|
||||
<rom label="vfs.lib.so"/>
|
||||
<rom label="vfs_pipe.lib.so"/>
|
||||
</content>
|
||||
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
<start name="test-libc_pipe">
|
||||
<default caps="256"/>
|
||||
<start name="pipes_fs">
|
||||
<binary name="vfs"/>
|
||||
<provides> <service name="File_system"/> </provides>
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log"/>
|
||||
<vfs> <pipe/> </vfs>
|
||||
<default-policy root="/" writeable="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="sequence">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<start name="libc_pipe_local">
|
||||
<binary name="test-libc_pipe"/>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="dev">
|
||||
<dir name="pipe"> <pipe/> </dir>
|
||||
<log/>
|
||||
</dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" pipe="/dev/pipe"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="libc_pipe_remote">
|
||||
<binary name="test-libc_pipe"/>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="dev">
|
||||
<dir name="pipe"> <fs/> </dir>
|
||||
<log/>
|
||||
</dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" pipe="/dev/pipe"/>
|
||||
</config>
|
||||
</start>
|
||||
</config>
|
||||
</start>
|
||||
</config>
|
||||
|
@ -1,11 +1,2 @@
|
||||
SRC_DIR = src/test/libc_pipe
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
||||
|
||||
MIRROR_FROM_REP_DIR := include/libc-plugin \
|
||||
lib/mk/libc_pipe.mk \
|
||||
src/lib/libc_pipe
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR)
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
@ -78,6 +78,7 @@ class Libc::Vfs_plugin : public Plugin
|
||||
Constructible<Genode::Directory> _root_dir { };
|
||||
Vfs::Io_response_handler &_response_handler;
|
||||
Update_mtime const _update_mtime;
|
||||
bool const _pipe_configured;
|
||||
|
||||
/**
|
||||
* Sync a handle and propagate errors
|
||||
@ -102,6 +103,14 @@ class Libc::Vfs_plugin : public Plugin
|
||||
template <typename FN>
|
||||
void _with_info(File_descriptor &fd, FN const &fn);
|
||||
|
||||
static bool _init_pipe_configured(Xml_node config)
|
||||
{
|
||||
bool result = false;
|
||||
config.with_sub_node("libc", [&] (Xml_node libc_node) {
|
||||
result = libc_node.has_attribute("pipe"); });
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vfs_plugin(Libc::Env &env,
|
||||
@ -114,7 +123,8 @@ class Libc::Vfs_plugin : public Plugin
|
||||
_alloc(alloc),
|
||||
_root_fs(env.vfs()),
|
||||
_response_handler(handler),
|
||||
_update_mtime(update_mtime)
|
||||
_update_mtime(update_mtime),
|
||||
_pipe_configured(_init_pipe_configured(config))
|
||||
{
|
||||
if (config.has_sub_node("libc"))
|
||||
_root_dir.construct(vfs_env);
|
||||
@ -134,6 +144,7 @@ class Libc::Vfs_plugin : public Plugin
|
||||
bool supports_access(const char *, int) override { return true; }
|
||||
bool supports_mkdir(const char *, mode_t) override { return true; }
|
||||
bool supports_open(const char *, int) override { return true; }
|
||||
bool supports_pipe() override { return _pipe_configured; }
|
||||
bool supports_poll() override { return true; }
|
||||
bool supports_readlink(const char *, char *, ::size_t) override { return true; }
|
||||
bool supports_rename(const char *, const char *) override { return true; }
|
||||
@ -167,6 +178,7 @@ class Libc::Vfs_plugin : public Plugin
|
||||
int ioctl(File_descriptor *, int , char *) override;
|
||||
::off_t lseek(File_descriptor *fd, ::off_t offset, int whence) override;
|
||||
int mkdir(const char *, mode_t) override;
|
||||
int pipe(File_descriptor *pipefdo[2]) override;
|
||||
bool poll(File_descriptor &fdo, struct pollfd &pfd) override;
|
||||
ssize_t read(File_descriptor *, void *, ::size_t) override;
|
||||
ssize_t readlink(const char *, char *, ::size_t) override;
|
||||
|
@ -166,6 +166,13 @@ namespace Libc {
|
||||
char const *string() const { return _value.string(); }
|
||||
};
|
||||
|
||||
char const *config_pipe() __attribute__((weak));
|
||||
char const *config_pipe()
|
||||
{
|
||||
static Config_attr attr("pipe", "");
|
||||
return attr.string();
|
||||
}
|
||||
|
||||
char const *config_rng() __attribute__((weak));
|
||||
char const *config_rng()
|
||||
{
|
||||
@ -1599,6 +1606,65 @@ int Libc::Vfs_plugin::munmap(void *addr, ::size_t)
|
||||
}
|
||||
|
||||
|
||||
int Libc::Vfs_plugin::pipe(Libc::File_descriptor *pipefdo[2])
|
||||
{
|
||||
Absolute_path base_path(Libc::config_pipe());
|
||||
if (base_path == "") {
|
||||
error(__func__, ": pipe fs not mounted");
|
||||
return Errno(EACCES);
|
||||
}
|
||||
|
||||
Libc::File_descriptor *meta_fd { nullptr };
|
||||
|
||||
{
|
||||
Absolute_path new_path = base_path;
|
||||
new_path.append("/new");
|
||||
|
||||
meta_fd = open(new_path.base(), O_RDONLY, Libc::ANY_FD);
|
||||
if (!meta_fd) {
|
||||
Genode::error("failed to create pipe at ", new_path);
|
||||
return Errno(EACCES);
|
||||
}
|
||||
meta_fd->path(new_path.string());
|
||||
|
||||
char buf[32] { };
|
||||
int const n = read(meta_fd, buf, sizeof(buf)-1);
|
||||
if (n < 1) {
|
||||
error("failed to read pipe at ", new_path);
|
||||
close(meta_fd);
|
||||
return Errno(EACCES);
|
||||
}
|
||||
buf[n] = '\0';
|
||||
base_path.append("/");
|
||||
base_path.append(buf);
|
||||
}
|
||||
|
||||
auto open_pipe_fd = [&] (auto path_suffix, auto flags)
|
||||
{
|
||||
Absolute_path path = base_path;
|
||||
path.append(path_suffix);
|
||||
|
||||
File_descriptor *fd = open(path.base(), flags, Libc::ANY_FD);
|
||||
if (!fd)
|
||||
error("failed to open pipe end at ", path);
|
||||
else
|
||||
fd->path(path.string());
|
||||
|
||||
return fd;
|
||||
};
|
||||
|
||||
pipefdo[0] = open_pipe_fd("/out", O_RDONLY);
|
||||
pipefdo[1] = open_pipe_fd("/in", O_WRONLY);
|
||||
|
||||
close(meta_fd);
|
||||
|
||||
if (!pipefdo[0] || !pipefdo[1])
|
||||
return Errno(EACCES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool Libc::Vfs_plugin::poll(File_descriptor &fd, struct pollfd &pfd)
|
||||
{
|
||||
if (fd.plugin != this) return false;
|
||||
|
@ -76,7 +76,8 @@ int main(int argc, char *argv[])
|
||||
ssize_t bytes_written = write(pipefd[1], buf, BUF_SIZE);
|
||||
|
||||
if (bytes_written != BUF_SIZE) {
|
||||
fprintf(stderr, "Error writing to pipe\n");
|
||||
fprintf(stderr, "Error writing to pipe (bytes_written=%zd, BUF_SIZE=%zd)\n",
|
||||
bytes_written, (size_t)BUF_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
TARGET = test-libc_pipe
|
||||
LIBS = base posix libc_pipe
|
||||
LIBS = base posix
|
||||
SRC_CC = main.cc
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
||||
|
Reference in New Issue
Block a user