mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
libc: use Id_space for FD allocator
This patch replaces the former use of an Allocator_avl with the Id_space utility, which is safer to use and allows for the iteration of all elements. The iteration over open file descriptors is needed for implementing 'fork'. Issue #3478
This commit is contained in:
parent
354e310c87
commit
6e38b53001
@ -15,10 +15,11 @@
|
|||||||
#ifndef _LIBC_PLUGIN__FD_ALLOC_H_
|
#ifndef _LIBC_PLUGIN__FD_ALLOC_H_
|
||||||
#define _LIBC_PLUGIN__FD_ALLOC_H_
|
#define _LIBC_PLUGIN__FD_ALLOC_H_
|
||||||
|
|
||||||
#include <base/allocator_avl.h>
|
|
||||||
#include <base/lock.h>
|
#include <base/lock.h>
|
||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
#include <os/path.h>
|
#include <os/path.h>
|
||||||
|
#include <base/allocator.h>
|
||||||
|
#include <base/id_space.h>
|
||||||
|
|
||||||
/* libc includes */
|
/* libc includes */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -39,13 +40,27 @@ namespace Libc {
|
|||||||
|
|
||||||
struct File_descriptor
|
struct File_descriptor
|
||||||
{
|
{
|
||||||
int libc_fd = -1;
|
Genode::Lock lock { };
|
||||||
char const *fd_path = 0; /* for 'fchdir', 'fstat' */
|
|
||||||
Plugin *plugin = 0;
|
typedef Genode::Id_space<File_descriptor> Id_space;
|
||||||
Plugin_context *context = 0;
|
Id_space::Element _elem;
|
||||||
int flags = 0; /* for 'fcntl' */
|
|
||||||
bool cloexec = 0; /* for 'fcntl' */
|
int const libc_fd = _elem.id().value;
|
||||||
Genode::Lock lock;
|
|
||||||
|
char const *fd_path = nullptr; /* for 'fchdir', 'fstat' */
|
||||||
|
|
||||||
|
Plugin *plugin;
|
||||||
|
Plugin_context *context;
|
||||||
|
|
||||||
|
int flags = 0; /* for 'fcntl' */
|
||||||
|
bool cloexec = 0; /* for 'fcntl' */
|
||||||
|
|
||||||
|
File_descriptor(Id_space &id_space, Plugin &plugin, Plugin_context &context)
|
||||||
|
: _elem(*this, id_space), plugin(&plugin), context(&context) { }
|
||||||
|
|
||||||
|
File_descriptor(Id_space &id_space, Plugin &plugin, Plugin_context &context,
|
||||||
|
Id_space::Id id)
|
||||||
|
: _elem(*this, id_space, id), plugin(&plugin), context(&context) { }
|
||||||
|
|
||||||
void path(char const *newpath)
|
void path(char const *newpath)
|
||||||
{
|
{
|
||||||
@ -54,8 +69,7 @@ namespace Libc {
|
|||||||
Genode::size_t const path_size = ::strlen(newpath) + 1;
|
Genode::size_t const path_size = ::strlen(newpath) + 1;
|
||||||
char *buf = (char*)malloc(path_size);
|
char *buf = (char*)malloc(path_size);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
Genode::error("could not allocate path buffer for libc_fd ",
|
Genode::error("could not allocate path buffer for libc_fd ", libc_fd);
|
||||||
libc_fd, libc_fd == ANY_FD ? " (any)" : "");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
::memcpy(buf, newpath, path_size);
|
::memcpy(buf, newpath, path_size);
|
||||||
@ -66,18 +80,24 @@ namespace Libc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class File_descriptor_allocator : Allocator_avl_tpl<File_descriptor>
|
class File_descriptor_allocator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Lock _lock;
|
Genode::Lock _lock;
|
||||||
|
|
||||||
|
Genode::Allocator &_alloc;
|
||||||
|
|
||||||
|
typedef File_descriptor::Id_space Id_space;
|
||||||
|
|
||||||
|
Id_space _id_space;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
File_descriptor_allocator(Genode::Allocator &md_alloc);
|
File_descriptor_allocator(Genode::Allocator &_alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate file descriptor
|
* Allocate file descriptor
|
||||||
|
@ -40,11 +40,9 @@ File_descriptor_allocator *Libc::file_descriptor_allocator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
File_descriptor_allocator::File_descriptor_allocator(Genode::Allocator &md_alloc)
|
File_descriptor_allocator::File_descriptor_allocator(Genode::Allocator &alloc)
|
||||||
: Allocator_avl_tpl<File_descriptor>(&md_alloc)
|
: _alloc(alloc)
|
||||||
{
|
{ }
|
||||||
add_range(0, MAX_NUM_FDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
File_descriptor *File_descriptor_allocator::alloc(Plugin *plugin,
|
File_descriptor *File_descriptor_allocator::alloc(Plugin *plugin,
|
||||||
@ -53,44 +51,41 @@ File_descriptor *File_descriptor_allocator::alloc(Plugin *plugin,
|
|||||||
{
|
{
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
|
|
||||||
/* we use addresses returned by the allocator as file descriptors */
|
bool const any_fd = (libc_fd < 0);
|
||||||
addr_t addr = (libc_fd <= ANY_FD ? ANY_FD : libc_fd);
|
if (any_fd)
|
||||||
|
return new (_alloc) File_descriptor(_id_space, *plugin, *context);
|
||||||
|
|
||||||
/* allocate fresh fd if the default value for 'libc_fd' was specified */
|
Id_space::Id const id {(unsigned)libc_fd};
|
||||||
bool alloc_ok = false;
|
return new (_alloc) File_descriptor(_id_space, *plugin, *context, id);
|
||||||
if (libc_fd <= ANY_FD)
|
|
||||||
alloc_ok = Allocator_avl_base::alloc_aligned(1, reinterpret_cast<void**>(&addr), 0).ok();
|
|
||||||
else
|
|
||||||
alloc_ok = (Allocator_avl_base::alloc_addr(1, addr).ok());
|
|
||||||
|
|
||||||
if (!alloc_ok) {
|
|
||||||
error("could not allocate libc_fd ", libc_fd,
|
|
||||||
libc_fd <= ANY_FD ? " (any)" : "");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
File_descriptor *fdo = metadata((void*)addr);
|
|
||||||
fdo->libc_fd = (int)addr;
|
|
||||||
fdo->fd_path = 0;
|
|
||||||
fdo->plugin = plugin;
|
|
||||||
fdo->context = context;
|
|
||||||
fdo->lock = Lock(Lock::UNLOCKED);
|
|
||||||
return fdo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void File_descriptor_allocator::free(File_descriptor *fdo)
|
void File_descriptor_allocator::free(File_descriptor *fdo)
|
||||||
{
|
{
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
|
|
||||||
::free((void *)fdo->fd_path);
|
::free((void *)fdo->fd_path);
|
||||||
Allocator_avl_base::free(reinterpret_cast<void*>(fdo->libc_fd));
|
|
||||||
|
Genode::destroy(_alloc, fdo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
File_descriptor *File_descriptor_allocator::find_by_libc_fd(int libc_fd)
|
File_descriptor *File_descriptor_allocator::find_by_libc_fd(int libc_fd)
|
||||||
{
|
{
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
return metadata(reinterpret_cast<void*>(libc_fd));
|
|
||||||
|
if (libc_fd < 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
File_descriptor *result = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Id_space::Id const id {(unsigned)libc_fd};
|
||||||
|
_id_space.apply<File_descriptor>(id, [&] (File_descriptor &fd) {
|
||||||
|
result = &fd; });
|
||||||
|
} catch (Id_space::Unknown_id) { }
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user