mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
vfs_gpu: VFS plugin that handles GPU completions
When a <gpu> node is present in the VFS, the plugin opens a Gpu::Connection for each open call to the 'gpu' node and installs a completion signal handler. A read only to the fd returned only comes back if a completion signal has been received between two read transctions to the fd. For now the Gpu::Connections can be retrieved by calling the 'vfs_gpu_connection(unsigned long id)' function. The id can be obtained using 'stat' on the 'gpu' device and is located in the inode (st_ino) field of the stat buffer. issue #4380
This commit is contained in:
parent
b7d25636e5
commit
b3e12dcece
6
repos/gems/lib/mk/vfs_gpu.mk
Normal file
6
repos/gems/lib/mk/vfs_gpu.mk
Normal file
@ -0,0 +1,6 @@
|
||||
SRC_CC = vfs.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/vfs/gpu
|
||||
|
||||
SHARED_LIB = yes
|
||||
CC_CXX_WARN_STRICT =
|
9
repos/gems/recipes/src/vfs_gpu/content.mk
Normal file
9
repos/gems/recipes/src/vfs_gpu/content.mk
Normal file
@ -0,0 +1,9 @@
|
||||
MIRROR_FROM_REP_DIR := lib/mk/vfs_gpu.mk src/lib/vfs/gpu
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) LICENSE
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
LICENSE:
|
||||
cp $(GENODE_DIR)/LICENSE $@
|
1
repos/gems/recipes/src/vfs_gpu/hash
Normal file
1
repos/gems/recipes/src/vfs_gpu/hash
Normal file
@ -0,0 +1 @@
|
||||
2021-11-25 5b57237a277a78a2c4cca4afb8caf919d5ef79b3
|
6
repos/gems/recipes/src/vfs_gpu/used_apis
Normal file
6
repos/gems/recipes/src/vfs_gpu/used_apis
Normal file
@ -0,0 +1,6 @@
|
||||
base
|
||||
os
|
||||
so
|
||||
vfs
|
||||
gems
|
||||
gpu_session
|
1
repos/gems/src/lib/vfs/gpu/target.mk
Normal file
1
repos/gems/src/lib/vfs/gpu/target.mk
Normal file
@ -0,0 +1 @@
|
||||
LIBS = vfs_gpu
|
183
repos/gems/src/lib/vfs/gpu/vfs.cc
Normal file
183
repos/gems/src/lib/vfs/gpu/vfs.cc
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* \brief Minimal file system for GPU session
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2021-10-14
|
||||
*
|
||||
* The file system only handles completion signals of the GPU session in order
|
||||
* to work from non-EP threads (i.e., pthreads) in libc components. A read
|
||||
* returns only in case a completion signal has been delivered since the
|
||||
* previous call to read.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#include <gpu_session/connection.h>
|
||||
#include <os/vfs.h>
|
||||
#include <util/xml_generator.h>
|
||||
#include <vfs/single_file_system.h>
|
||||
|
||||
namespace Vfs_gpu
|
||||
{
|
||||
using namespace Vfs;
|
||||
using namespace Genode;
|
||||
|
||||
struct File_system;
|
||||
}
|
||||
|
||||
struct Vfs_gpu::File_system : Single_file_system
|
||||
{
|
||||
struct Gpu_vfs_handle : Single_vfs_handle
|
||||
{
|
||||
bool _complete { false };
|
||||
Genode::Env &_env;
|
||||
Gpu::Connection _gpu_session { _env };
|
||||
|
||||
Genode::Io_signal_handler<Gpu_vfs_handle> _completion_sigh {
|
||||
_env.ep(), *this, &Gpu_vfs_handle::_handle_completion };
|
||||
|
||||
using Id_space = Genode::Id_space<Gpu_vfs_handle>;
|
||||
Id_space::Element const _elem;
|
||||
|
||||
void _handle_completion()
|
||||
{
|
||||
_complete = true;
|
||||
io_progress_response();
|
||||
}
|
||||
|
||||
Gpu_vfs_handle(Genode::Env &env,
|
||||
Directory_service &ds,
|
||||
File_io_service &fs,
|
||||
Genode::Allocator &alloc,
|
||||
Id_space &space)
|
||||
: Single_vfs_handle(ds, fs, alloc, 0),
|
||||
_env(env), _elem(*this, space)
|
||||
{
|
||||
_gpu_session.completion_sigh(_completion_sigh);
|
||||
}
|
||||
|
||||
Read_result read(char *dst, file_size /* count */,
|
||||
file_size &out_count) override
|
||||
{
|
||||
if (!_complete) return READ_QUEUED;
|
||||
|
||||
_complete = false;
|
||||
dst[0] = 1;
|
||||
out_count = 1;
|
||||
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
Write_result write(char const *, file_size, file_size &) override
|
||||
{
|
||||
return WRITE_ERR_IO;
|
||||
}
|
||||
|
||||
bool read_ready() override { return _complete; }
|
||||
|
||||
Id_space::Id id() const { return _elem.id(); }
|
||||
};
|
||||
|
||||
Vfs::Env &_env;
|
||||
|
||||
typedef String<32> Config;
|
||||
|
||||
Id_space<Gpu_vfs_handle> _handle_space { };
|
||||
Id_space<Gpu_vfs_handle>::Id _last_id { .value = ~0ul };
|
||||
|
||||
File_system(Vfs::Env &env, Xml_node config)
|
||||
:
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE,
|
||||
type_name(),
|
||||
Node_rwx::ro(),
|
||||
config),
|
||||
_env(env)
|
||||
{ }
|
||||
|
||||
Open_result open(char const *path, unsigned,
|
||||
Vfs::Vfs_handle **out_handle,
|
||||
Allocator &alloc) override
|
||||
{
|
||||
if (!_single_file(path))
|
||||
return OPEN_ERR_UNACCESSIBLE;
|
||||
|
||||
try {
|
||||
Gpu_vfs_handle *handle = new (alloc)
|
||||
Gpu_vfs_handle(_env.env(), *this, *this, alloc, _handle_space);
|
||||
|
||||
_last_id = handle->id();
|
||||
*out_handle = handle;
|
||||
|
||||
return OPEN_OK;
|
||||
}
|
||||
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
|
||||
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
|
||||
}
|
||||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
if (!_single_file(path))
|
||||
return STAT_ERR_NO_ENTRY;
|
||||
|
||||
out.inode = (unsigned long)_last_id.value;
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
static char const *type_name() { return "gpu"; }
|
||||
char const *type() override { return type_name(); }
|
||||
};
|
||||
|
||||
|
||||
static Vfs_gpu::File_system *_fs { nullptr };
|
||||
|
||||
|
||||
/**
|
||||
* XXX: return GPU session for given ID, retrieved by 'stat->inode'.
|
||||
* This function is used, for example, by libdrm via (dlopen/dlsym).
|
||||
*/
|
||||
Gpu::Connection *vfs_gpu_connection(unsigned long id)
|
||||
{
|
||||
if (!_fs) return nullptr;
|
||||
|
||||
using Gpu_vfs_handle = Vfs_gpu::File_system::Gpu_vfs_handle;
|
||||
using Id_space = Genode::Id_space<Gpu_vfs_handle>;
|
||||
|
||||
try {
|
||||
return _fs->_handle_space.apply<Gpu_vfs_handle>(
|
||||
Id_space::Id { .value = id },
|
||||
[] (Gpu_vfs_handle &handle) {
|
||||
return &handle._gpu_session; });
|
||||
} catch (...) { }
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
** VFS plugin interface **
|
||||
**************************/
|
||||
|
||||
extern "C" Vfs::File_system_factory *vfs_file_system_factory(void)
|
||||
{
|
||||
struct Factory : Vfs::File_system_factory
|
||||
{
|
||||
Vfs::File_system *create(Vfs::Env &vfs_env,
|
||||
Genode::Xml_node node) override
|
||||
{
|
||||
try {
|
||||
_fs = new (vfs_env.alloc()) Vfs_gpu::File_system(vfs_env, node);
|
||||
return _fs;
|
||||
}
|
||||
catch (...) { Genode::error("could not create 'gpu_fs' "); }
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
static Factory factory;
|
||||
return &factory;
|
||||
}
|
Loading…
Reference in New Issue
Block a user