mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
rump_fs: Transition to new API
The rump libraries and the rump_fs component are now conform to the new base API. Also the I/O back end should be running stable now. issue #2224
This commit is contained in:
parent
a7f40b24ca
commit
6fa6d72c0b
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* \brief Rump initialization
|
||||
* \author Norman Feske
|
||||
* \date 2016-11-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#ifndef _INCLUDE__RUMP__BOOTSTRAP_H_
|
||||
#define _INCLUDE__RUMP__BOOTSTRAP_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/allocator.h>
|
||||
|
||||
void rump_bootstrap_init(Genode::Env &env, Genode::Allocator &heap);
|
||||
|
||||
#endif /* _INCLUDE__RUMP__BOOTSTRAP_H_ */
|
47
repos/dde_rump/include/rump/env.h
Normal file
47
repos/dde_rump/include/rump/env.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Helper class to make the Genode Env globally available
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-06-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__RUMP__ENV_H_
|
||||
#define _INCLUDE__RUMP__ENV_H_
|
||||
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
namespace Rump {
|
||||
class Env;
|
||||
|
||||
Env &env();
|
||||
|
||||
void construct_env(Genode::Env &env);
|
||||
}
|
||||
|
||||
class Rump::Env
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
public:
|
||||
|
||||
Env(Genode::Env &env) : _env(env) { }
|
||||
|
||||
Genode::Env &env() { return _env; }
|
||||
Genode::Heap &heap() { return _heap; }
|
||||
Genode::Attached_rom_dataspace &config_rom() { return _config; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__RUMP__ENV_H_ */
|
@ -24,6 +24,8 @@
|
||||
#define GENODE_DEVICE "/genode"
|
||||
|
||||
|
||||
void rump_io_backend_init();
|
||||
|
||||
/**
|
||||
* Sync I/O back-end with underlying Genode subsystems
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <dataspace/client.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
#include <rump/env.h>
|
||||
|
||||
namespace Allocator {
|
||||
template <unsigned VM_SIZE, typename POLICY> class Backend_alloc;
|
||||
@ -85,7 +85,7 @@ namespace Allocator {
|
||||
Policy_guard<POLICY> guard;
|
||||
|
||||
try {
|
||||
_ds_cap[_index] = Genode::env()->ram_session()->alloc(BLOCK_SIZE, _cached);
|
||||
_ds_cap[_index] = Rump::env().env().ram().alloc(BLOCK_SIZE, _cached);
|
||||
/* attach at index * BLOCK_SIZE */
|
||||
Region_map_client::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
|
||||
/* lookup phys. address */
|
||||
@ -114,10 +114,10 @@ namespace Allocator {
|
||||
:
|
||||
Region_map_client(Rm_connection::create(VM_SIZE)),
|
||||
_cached(cached),
|
||||
_range(Genode::env()->heap())
|
||||
_range(&Rump::env().heap())
|
||||
{
|
||||
/* reserver attach us, anywere */
|
||||
_base = Genode::env()->rm_session()->attach(dataspace());
|
||||
_base = Rump::env().env().rm().attach(dataspace());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,8 @@ extern "C" {
|
||||
|
||||
#include <base/thread.h>
|
||||
#include <base/log.h>
|
||||
#include <rump/env.h>
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
|
||||
/*************
|
||||
@ -35,12 +37,17 @@ namespace Timer {
|
||||
};
|
||||
|
||||
|
||||
class Hard_context
|
||||
class Hard_context : public Genode::Avl_node<Hard_context>
|
||||
{
|
||||
private:
|
||||
|
||||
int _cookie;
|
||||
lwp *_lwp = 0;
|
||||
lwp *_lwp = nullptr;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Genode::Thread *_myself = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
@ -50,12 +57,65 @@ class Hard_context
|
||||
void set_lwp(lwp *l) { _lwp = l; }
|
||||
lwp *get_lwp() { return _lwp; }
|
||||
|
||||
static Timer::Connection *timer();
|
||||
static Timer::Connection &timer();
|
||||
|
||||
bool higher(Hard_context *h) { return _myself > h->_myself; }
|
||||
|
||||
Hard_context *find(Genode::Thread const *t)
|
||||
{
|
||||
if (_myself == t)
|
||||
return this;
|
||||
|
||||
Hard_context *h = child(_myself > t);
|
||||
if (!h)
|
||||
return nullptr;
|
||||
|
||||
return h->find(t);
|
||||
}
|
||||
|
||||
void thread(Genode::Thread *t) { _myself = t; }
|
||||
};
|
||||
|
||||
|
||||
class Hard_context_registry : public Genode::Avl_tree<Hard_context>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Lock lock;
|
||||
|
||||
public:
|
||||
|
||||
Hard_context *find(Genode::Thread const *t)
|
||||
{
|
||||
Genode::Lock::Guard g(lock);
|
||||
if (!first())
|
||||
return nullptr;
|
||||
|
||||
return first()->find(t);
|
||||
}
|
||||
|
||||
void insert(Hard_context *h)
|
||||
{
|
||||
Genode::Lock::Guard g(lock);
|
||||
Avl_tree::insert(h);
|
||||
}
|
||||
|
||||
void remove(Hard_context *h)
|
||||
{
|
||||
Genode::Lock::Guard g(lock);
|
||||
Avl_tree::remove(h);
|
||||
}
|
||||
|
||||
static Hard_context_registry &r()
|
||||
{
|
||||
static Hard_context_registry _r;
|
||||
return _r;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Hard_context_thread : public Hard_context,
|
||||
public Genode::Thread_deprecated<sizeof(Genode::addr_t) * 2048>
|
||||
public Genode::Thread
|
||||
{
|
||||
private:
|
||||
|
||||
@ -66,14 +126,17 @@ class Hard_context_thread : public Hard_context,
|
||||
|
||||
void entry()
|
||||
{
|
||||
Hard_context::thread(Genode::Thread::myself());
|
||||
Hard_context_registry::r().insert(this);
|
||||
_func(_arg);
|
||||
Hard_context_registry::r().remove(this);
|
||||
Genode::log(__func__, " returned from func");
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Hard_context_thread(char const *name, func f, void *arg, int cookie, bool run = true)
|
||||
: Hard_context(cookie), Thread_deprecated(name),
|
||||
: Hard_context(cookie), Thread(Rump::env().env(), name, sizeof(long) * 2048),
|
||||
_func(f), _arg(arg) { if (run) start(); }
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,7 @@ VERBOSE_LEVEL ?= 0
|
||||
#
|
||||
# Sources
|
||||
#
|
||||
SRC_CC = dummies.cc hypercall.cc bootstrap.cc io.cc sync.cc misc.cc
|
||||
SRC_CC = dummies.cc hypercall.cc bootstrap.cc io.cc sync.cc misc.cc env.cc
|
||||
|
||||
#
|
||||
# TARGET to trigger rump build
|
||||
|
@ -85,7 +85,7 @@ install_config $config
|
||||
set boot_modules {
|
||||
core ld.lib.so init timer test-libc_vfs ram_blk
|
||||
rump.lib.so rump_fs.lib.so rump_fs
|
||||
ext2.raw libc.lib.so
|
||||
ext2.raw libc.lib.so libm.lib.so
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
@ -17,11 +17,13 @@ extern "C" {
|
||||
#include <elf.h>
|
||||
}
|
||||
|
||||
#include <rump/bootstrap.h>
|
||||
#include <rump/env.h>
|
||||
|
||||
#include <base/log.h>
|
||||
#include <base/shared_object.h>
|
||||
#include <util/string.h>
|
||||
|
||||
|
||||
extern "C" void wait_for_continue();
|
||||
|
||||
#ifdef _LP64
|
||||
@ -36,46 +38,20 @@ static bool const verbose = false;
|
||||
|
||||
|
||||
static Genode::Shared_object *obj_main;
|
||||
static Genode::Env *env_ptr;
|
||||
static Genode::Allocator *heap_ptr;
|
||||
|
||||
|
||||
void rump_bootstrap_init(Genode::Env &env, Genode::Allocator &alloc)
|
||||
{
|
||||
/* ignore subsequent calls */
|
||||
if (env_ptr)
|
||||
return;
|
||||
|
||||
env_ptr = &env;
|
||||
heap_ptr = &alloc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Missing_call_of_rump_bootstrap_init { };
|
||||
|
||||
|
||||
static Genode::Env &env()
|
||||
{
|
||||
if (!env_ptr)
|
||||
throw Missing_call_of_rump_bootstrap_init();
|
||||
|
||||
return *env_ptr;
|
||||
return Rump::env().env();
|
||||
}
|
||||
|
||||
|
||||
static Genode::Allocator &heap()
|
||||
{
|
||||
if (!heap_ptr)
|
||||
throw Missing_call_of_rump_bootstrap_init();
|
||||
|
||||
return *heap_ptr;
|
||||
return Rump::env().heap();
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct Sym_tab
|
||||
{
|
||||
Genode::Shared_object::Link_map const *map;
|
||||
@ -119,7 +95,7 @@ struct Sym_tab
|
||||
~Sym_tab()
|
||||
{
|
||||
if (sym_tab)
|
||||
destroy(Genode::env()->heap(), sym_tab);
|
||||
destroy(heap(), sym_tab);
|
||||
}
|
||||
|
||||
|
||||
@ -186,7 +162,7 @@ struct Sym_tab
|
||||
|
||||
void alloc_memory()
|
||||
{
|
||||
sym_tab = (Elf_Sym *)Genode::env()->heap()->alloc(sizeof(Elf_Sym) * sym_cnt);
|
||||
sym_tab = (Elf_Sym *)heap().alloc(sizeof(Elf_Sym) * sym_cnt);
|
||||
}
|
||||
|
||||
void read_symbols()
|
||||
|
31
repos/dde_rump/src/lib/rump/env.cc
Normal file
31
repos/dde_rump/src/lib/rump/env.cc
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* \brief Rump::Env initialization
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-06-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <rump/env.h>
|
||||
|
||||
/*
|
||||
* Genode nviroment instance
|
||||
*/
|
||||
static Genode::Constructible<Rump::Env> _env;
|
||||
|
||||
|
||||
Rump::Env &Rump::env()
|
||||
{
|
||||
return *_env;
|
||||
}
|
||||
|
||||
|
||||
void Rump::construct_env(Genode::Env &env)
|
||||
{
|
||||
_env.construct(env);
|
||||
}
|
@ -14,10 +14,10 @@
|
||||
|
||||
#include "sched.h"
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <os/timed_semaphore.h>
|
||||
#include <rump/env.h>
|
||||
#include <util/allocator_fap.h>
|
||||
#include <util/random.h>
|
||||
#include <util/string.h>
|
||||
@ -31,53 +31,32 @@ static bool verbose = false;
|
||||
struct rumpuser_hyperup _rump_upcalls;
|
||||
|
||||
|
||||
/********************
|
||||
** Initialization **
|
||||
********************/
|
||||
|
||||
int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
|
||||
{
|
||||
Genode::log("RUMP ver: ", version);
|
||||
if (version != SUPPORTED_RUMP_VERSION) {
|
||||
Genode::error("unsupported rump-kernel version (", version, ") - "
|
||||
"supported is ", (int)SUPPORTED_RUMP_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_rump_upcalls = *hyp;
|
||||
|
||||
/*
|
||||
* Start 'Timeout_thread' so it does not get constructed concurrently (which
|
||||
* causes one thread to spin in cxa_guard_aqcuire), making emulation *really*
|
||||
* slow
|
||||
*/
|
||||
Genode::Timeout_thread::alarm_timer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*************
|
||||
** Threads **
|
||||
*************/
|
||||
|
||||
static Hard_context * main_thread()
|
||||
static Hard_context *main_context()
|
||||
{
|
||||
static Hard_context inst(0);
|
||||
return &inst;
|
||||
}
|
||||
|
||||
|
||||
static Hard_context *myself()
|
||||
{
|
||||
Hard_context *h = dynamic_cast<Hard_context *>(Genode::Thread::myself());
|
||||
return h ? h : main_thread();
|
||||
Hard_context *h = Hard_context_registry::r().find(Genode::Thread::myself());
|
||||
|
||||
if (!h)
|
||||
Genode::error("Hard context is nullptr (", Genode::Thread::myself(), ")");
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
Timer::Connection *Hard_context::timer()
|
||||
Timer::Connection &Hard_context::timer()
|
||||
{
|
||||
static Timer::Connection _timer;
|
||||
return &_timer;
|
||||
static Timer::Connection _timer { Rump::env().env() };
|
||||
return _timer;
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +91,7 @@ int rumpuser_thread_create(func f, void *arg, const char *name,
|
||||
if (mustjoin)
|
||||
*cookie = (void *)++count;
|
||||
|
||||
new (Genode::env()->heap()) Hard_context_thread(name, f, arg, mustjoin ? count : 0);
|
||||
new (Rump::env().heap()) Hard_context_thread(name, f, arg, mustjoin ? count : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -128,6 +107,37 @@ int errno;
|
||||
void rumpuser_seterrno(int e) { errno = e; }
|
||||
|
||||
|
||||
/********************
|
||||
** Initialization **
|
||||
********************/
|
||||
|
||||
int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
|
||||
{
|
||||
Genode::log("RUMP ver: ", version);
|
||||
if (version != SUPPORTED_RUMP_VERSION) {
|
||||
Genode::error("unsupported rump-kernel version (", version, ") - "
|
||||
"supported is ", (int)SUPPORTED_RUMP_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_rump_upcalls = *hyp;
|
||||
|
||||
/* register context for main EP */
|
||||
main_context()->thread(Genode::Thread::myself());
|
||||
Hard_context_registry::r().insert(main_context());
|
||||
|
||||
/*
|
||||
* Start 'Timeout_thread' so it does not get constructed concurrently (which
|
||||
* causes one thread to spin in cxa_guard_aqcuire), making emulation *really*
|
||||
* slow
|
||||
*/
|
||||
Genode::Timeout_thread::alarm_timer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************
|
||||
** Parameter retrieval **
|
||||
*************************/
|
||||
@ -152,7 +162,7 @@ int rumpuser_getparam(const char *name, void *buf, size_t buflen)
|
||||
if (!Genode::strcmp(name, "RUMP_MEMLIMIT")) {
|
||||
|
||||
/* leave 2 MB for the Genode */
|
||||
size_t rump_ram = Genode::env()->ram_session()->avail();
|
||||
size_t rump_ram = Rump::env().env().ram().avail();
|
||||
|
||||
if (rump_ram <= RESERVE_MEM) {
|
||||
Genode::error("insufficient quota left: ",
|
||||
@ -178,20 +188,22 @@ int rumpuser_getparam(const char *name, void *buf, size_t buflen)
|
||||
|
||||
void rumpuser_putchar(int ch)
|
||||
{
|
||||
static unsigned char buf[256];
|
||||
enum { BUF_SIZE = 256 };
|
||||
static unsigned char buf[BUF_SIZE];
|
||||
static int count = 0;
|
||||
|
||||
buf[count++] = (unsigned char)ch;
|
||||
if (count < BUF_SIZE - 1 && ch != '\n')
|
||||
buf[count++] = (unsigned char)ch;
|
||||
|
||||
if (ch == '\n') {
|
||||
if (ch == '\n' || count == BUF_SIZE - 1) {
|
||||
buf[count] = 0;
|
||||
int nlocks;
|
||||
if (myself() != main_thread())
|
||||
if (myself() != main_context())
|
||||
rumpkern_unsched(&nlocks, 0);
|
||||
|
||||
Genode::log("rump: ", Genode::Cstring((char const *)buf));
|
||||
|
||||
if (myself() != main_thread())
|
||||
if (myself() != main_context())
|
||||
rumpkern_sched(nlocks, 0);
|
||||
|
||||
count = 0;
|
||||
@ -209,14 +221,14 @@ struct Allocator_policy
|
||||
{
|
||||
int nlocks;
|
||||
|
||||
if (myself() != main_thread())
|
||||
if (myself() != main_context())
|
||||
rumpkern_unsched(&nlocks, 0);
|
||||
return nlocks;
|
||||
}
|
||||
|
||||
static void unblock(int nlocks)
|
||||
{
|
||||
if (myself() != main_thread())
|
||||
if (myself() != main_context())
|
||||
rumpkern_sched(nlocks, 0);
|
||||
}
|
||||
};
|
||||
@ -230,12 +242,14 @@ static Genode::Lock & alloc_lock()
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
static Rump_alloc* allocator()
|
||||
{
|
||||
static Rump_alloc _fap(true);
|
||||
return &_fap;
|
||||
}
|
||||
|
||||
|
||||
int rumpuser_malloc(size_t len, int alignment, void **memp)
|
||||
{
|
||||
Genode::Lock::Guard guard(alloc_lock());
|
||||
@ -269,7 +283,7 @@ void rumpuser_free(void *mem, size_t len)
|
||||
int rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
|
||||
{
|
||||
Hard_context *h = myself();
|
||||
unsigned long t = h->timer()->elapsed_ms();
|
||||
unsigned long t = h->timer().elapsed_ms();
|
||||
*sec = (int64_t)t / 1000;
|
||||
*nsec = (t % 1000) * 1000;
|
||||
return 0;
|
||||
@ -281,7 +295,7 @@ int rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
|
||||
int nlocks;
|
||||
unsigned int msec = 0;
|
||||
|
||||
Timer::Connection *timer = myself()->timer();
|
||||
Timer::Connection &timer = myself()->timer();
|
||||
|
||||
rumpkern_unsched(&nlocks, 0);
|
||||
switch (enum_rumpclock) {
|
||||
@ -289,12 +303,12 @@ int rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
|
||||
msec = sec * 1000 + nsec / (1000*1000UL);
|
||||
break;
|
||||
case RUMPUSER_CLOCK_ABSMONO:
|
||||
msec = timer->elapsed_ms();
|
||||
msec = timer.elapsed_ms();
|
||||
msec = ((sec * 1000) + (nsec / (1000 * 1000))) - msec;
|
||||
break;
|
||||
}
|
||||
|
||||
timer->msleep(msec);
|
||||
timer.msleep(msec);
|
||||
rumpkern_sched(nlocks, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* \brief Connect rump kernel Genode's block interface
|
||||
* \brief Connect rump kernel to Genode's block interface
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2013-12-16
|
||||
*/
|
||||
@ -13,218 +13,35 @@
|
||||
|
||||
#include "sched.h"
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/printf.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <rump/env.h>
|
||||
#include <rump_fs/fs.h>
|
||||
#include <util/list.h>
|
||||
#include <util/string.h>
|
||||
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
enum { GENODE_FD = 64 };
|
||||
|
||||
struct Packet : Genode::List<Packet>::Element
|
||||
/**
|
||||
* Block session connection
|
||||
*/
|
||||
class Backend
|
||||
{
|
||||
Block::sector_t blk;
|
||||
Genode::size_t cnt;
|
||||
Block::Packet_descriptor::Opcode opcode;
|
||||
void *data;
|
||||
long offset;
|
||||
rump_biodone_fn biodone;
|
||||
void *donearg;
|
||||
bool valid;
|
||||
bool pending;
|
||||
bool sync;
|
||||
};
|
||||
|
||||
|
||||
class Backend : public Hard_context_thread
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
enum { COUNT = Block::Session::TX_QUEUE_SIZE };
|
||||
|
||||
Genode::Allocator_avl _alloc;
|
||||
Block::Connection _session;
|
||||
Genode::Allocator_avl _alloc { &Rump::env().heap() };
|
||||
Block::Connection _session { Rump::env().env(), &_alloc };
|
||||
Genode::size_t _blk_size; /* block size of the device */
|
||||
Block::sector_t _blk_cnt; /* number of blocks of device */
|
||||
Block::Session::Operations _blk_ops;
|
||||
Packet _p[COUNT];
|
||||
Genode::Semaphore _alloc_sem;
|
||||
Genode::Semaphore _packet_sem;
|
||||
int _index_thread = 0;
|
||||
int _index_client = 0;
|
||||
Genode::Lock _alloc_lock;
|
||||
bool _handle;
|
||||
Genode::Signal_receiver _receiver;
|
||||
Genode::Signal_dispatcher<Backend> _disp_ack;
|
||||
Genode::Signal_dispatcher<Backend> _disp_submit;
|
||||
|
||||
|
||||
Genode::List<Packet> *_pending()
|
||||
{
|
||||
static Genode::List<Packet> _p;
|
||||
return &_p;
|
||||
}
|
||||
|
||||
bool _have_pending()
|
||||
{
|
||||
return !!_pending()->first();
|
||||
}
|
||||
|
||||
Packet *_find(Block::Packet_descriptor &packet)
|
||||
{
|
||||
Packet *p = _pending()->first();
|
||||
while (p) {
|
||||
if (p->offset == packet.offset())
|
||||
return p;
|
||||
|
||||
p = p->next();
|
||||
}
|
||||
|
||||
Genode::error("pending packet not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Packet *_dequeue()
|
||||
{
|
||||
int idx;
|
||||
for (int i = 0; i < COUNT; i++) {
|
||||
idx = (_index_thread + i) % COUNT;
|
||||
if (_p[idx].valid && !_p[idx].pending) {
|
||||
_index_thread = idx;
|
||||
_p[idx].pending = true;
|
||||
return &_p[idx];
|
||||
}
|
||||
}
|
||||
Genode::warning("dequeue returned 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void _free(Packet *p)
|
||||
{
|
||||
p->valid = false;
|
||||
p->pending = false;
|
||||
_alloc_sem.up();
|
||||
}
|
||||
|
||||
void _ready_to_submit(unsigned) { _handle = false; }
|
||||
|
||||
void _ack_avail(unsigned)
|
||||
{
|
||||
_handle = false;
|
||||
|
||||
while (_session.tx()->ack_avail()) {
|
||||
Block::Packet_descriptor packet = _session.tx()->get_acked_packet();
|
||||
Packet *p = _find(packet);
|
||||
|
||||
if (p->opcode == Block::Packet_descriptor::READ)
|
||||
Genode::memcpy(p->data, _session.tx()->packet_content(packet),
|
||||
packet.block_count() * _blk_size);
|
||||
|
||||
|
||||
/* sync session if requested */
|
||||
if (p->sync)
|
||||
_session.sync();
|
||||
|
||||
int dummy;
|
||||
if (verbose)
|
||||
Genode::log("BIO done p: ", p, " bio ", p->donearg);
|
||||
|
||||
rumpkern_sched(0, 0);
|
||||
if (p->biodone)
|
||||
p->biodone(p->donearg, p->cnt * _blk_size,
|
||||
packet.succeeded() ? 0 : EIO);
|
||||
rumpkern_unsched(&dummy, 0);
|
||||
|
||||
_session.tx()->release_packet(packet);
|
||||
_pending()->remove(p);
|
||||
_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void _handle_signal()
|
||||
{
|
||||
_handle = true;
|
||||
|
||||
while (_handle) {
|
||||
Genode::Signal s = _receiver.wait_for_signal();
|
||||
static_cast<Genode::Signal_dispatcher_base *>
|
||||
(s.context())->dispatch(s.num());
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void entry()
|
||||
{
|
||||
_rump_upcalls.hyp_schedule();
|
||||
_rump_upcalls.hyp_lwproc_newlwp(0);
|
||||
_rump_upcalls.hyp_unschedule();
|
||||
|
||||
while (true) {
|
||||
|
||||
while (_packet_sem.cnt() <= 0 && _have_pending())
|
||||
_handle_signal();
|
||||
|
||||
_packet_sem.down();
|
||||
|
||||
while (!_session.tx()->ready_to_submit())
|
||||
_handle_signal();
|
||||
|
||||
Packet *p = _dequeue();
|
||||
|
||||
/* zero or sync request */
|
||||
if (!p->cnt) {
|
||||
|
||||
if (p->sync)
|
||||
_session.sync();
|
||||
|
||||
_free(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (bool done = false; !done;)
|
||||
try {
|
||||
Block::Packet_descriptor packet(
|
||||
_session.dma_alloc_packet(p->cnt * _blk_size),
|
||||
p->opcode, p->blk, p->cnt);
|
||||
/* got packet copy data */
|
||||
if (p->opcode == Block::Packet_descriptor::WRITE)
|
||||
Genode::memcpy(_session.tx()->packet_content(packet),
|
||||
p->data, p->cnt * _blk_size);
|
||||
_session.tx()->submit_packet(packet);
|
||||
|
||||
/* mark as pending */
|
||||
p->offset = packet.offset();
|
||||
_pending()->insert(p);
|
||||
done = true;
|
||||
} catch(Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
_handle_signal();
|
||||
}
|
||||
}
|
||||
}
|
||||
Genode::Lock _session_lock;
|
||||
|
||||
public:
|
||||
|
||||
Backend()
|
||||
: Hard_context_thread("block_io", 0, 0, 0, false),
|
||||
_alloc(Genode::env()->heap()),
|
||||
_session(&_alloc),
|
||||
_alloc_sem(COUNT),
|
||||
_disp_ack(_receiver, *this, &Backend::_ack_avail),
|
||||
_disp_submit(_receiver, *this, &Backend::_ready_to_submit)
|
||||
{
|
||||
_session.tx_channel()->sigh_ack_avail(_disp_ack);
|
||||
_session.tx_channel()->sigh_ready_to_submit(_disp_submit);
|
||||
_session.info(&_blk_cnt, &_blk_size, &_blk_ops);
|
||||
Genode::log("Backend blk_size ", _blk_size);
|
||||
Genode::memset(_p, 0, sizeof(_p));
|
||||
start();
|
||||
}
|
||||
|
||||
uint64_t block_count() const { return (uint64_t)_blk_cnt; }
|
||||
@ -235,44 +52,61 @@ class Backend : public Hard_context_thread
|
||||
return _blk_ops.supported(Block::Packet_descriptor::WRITE);
|
||||
}
|
||||
|
||||
Packet *alloc()
|
||||
void sync()
|
||||
{
|
||||
int idx;
|
||||
_alloc_sem.down();
|
||||
Genode::Lock::Guard guard(_alloc_lock);
|
||||
for (int i = 0; i < COUNT; i++) {
|
||||
idx = (_index_client + i) % COUNT;
|
||||
if (!_p[idx].valid) {
|
||||
_p[idx].valid = true;
|
||||
_p[idx].pending = false;
|
||||
_index_client = idx;
|
||||
return &_p[idx];
|
||||
}
|
||||
}
|
||||
Genode::warning("alloc returned 0");
|
||||
return 0;
|
||||
Genode::Lock::Guard guard(_session_lock);
|
||||
_session.sync();
|
||||
}
|
||||
|
||||
void submit() { _packet_sem.up(); }
|
||||
bool submit(int op, int64_t offset, size_t length, void *data)
|
||||
{
|
||||
using namespace Block;
|
||||
|
||||
/* sync request */
|
||||
if (op & RUMPUSER_BIO_SYNC) {
|
||||
sync();
|
||||
return true;
|
||||
}
|
||||
|
||||
Genode::Lock::Guard guard(_session_lock);
|
||||
|
||||
Packet_descriptor::Opcode opcode;
|
||||
opcode = op & RUMPUSER_BIO_WRITE ? Packet_descriptor::WRITE :
|
||||
Packet_descriptor::READ;
|
||||
/* allocate packet */
|
||||
try {
|
||||
Packet_descriptor packet( _session.dma_alloc_packet(length),
|
||||
opcode, offset / _blk_size,
|
||||
length / _blk_size);
|
||||
|
||||
/* out packet -> copy data */
|
||||
if (opcode == Packet_descriptor::WRITE)
|
||||
Genode::memcpy(_session.tx()->packet_content(packet), data, length);
|
||||
|
||||
_session.tx()->submit_packet(packet);
|
||||
} catch(Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
Genode::error("I/O back end: Packet allocation failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* wait and process result */
|
||||
Packet_descriptor packet = _session.tx()->get_acked_packet();
|
||||
|
||||
/* in packet */
|
||||
if (opcode == Packet_descriptor::READ)
|
||||
Genode::memcpy(data, _session.tx()->packet_content(packet), length);
|
||||
|
||||
bool succeeded = packet.succeeded();
|
||||
_session.tx()->release_packet(packet);
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Backend *backend()
|
||||
static Backend &backend()
|
||||
{
|
||||
static Backend *_b = 0;
|
||||
|
||||
if (_b)
|
||||
return _b;
|
||||
|
||||
int nlocks;
|
||||
rumpkern_unsched(&nlocks, 0);
|
||||
try {
|
||||
_b = new(Genode::env()->heap())Backend();
|
||||
} catch (Genode::Parent::Service_denied) {
|
||||
Genode::error("opening block session denied!");
|
||||
}
|
||||
rumpkern_sched(nlocks, 0);
|
||||
|
||||
static Backend _b;
|
||||
return _b;
|
||||
}
|
||||
|
||||
@ -286,7 +120,7 @@ int rumpuser_getfileinfo(const char *name, uint64_t *size, int *type)
|
||||
*type = RUMPUSER_FT_BLK;
|
||||
|
||||
if (size)
|
||||
*size = backend()->block_count() * backend()->block_size();
|
||||
*size = backend().block_count() * backend().block_size();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -298,7 +132,7 @@ int rumpuser_open(const char *name, int mode, int *fdp)
|
||||
return ENXIO;
|
||||
|
||||
/* check for writable */
|
||||
if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend()->writable())
|
||||
if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend().writable())
|
||||
return EROFS;
|
||||
|
||||
*fdp = GENODE_FD;
|
||||
@ -310,40 +144,36 @@ void rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t off,
|
||||
rump_biodone_fn biodone, void *donearg)
|
||||
{
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, 0);
|
||||
Packet *p = backend()->alloc();
|
||||
|
||||
/* data request */
|
||||
if (verbose)
|
||||
Genode::log("fd: ", fd, " "
|
||||
"op: ", op, " "
|
||||
"len: ", dlen, " "
|
||||
"off: ", Genode::Hex((unsigned long)off), " "
|
||||
"p: ", p, " "
|
||||
"bio ", donearg, " "
|
||||
"sync: ", !!(op & RUMPUSER_BIO_SYNC));
|
||||
|
||||
p->opcode= op & RUMPUSER_BIO_WRITE ? Block::Packet_descriptor::WRITE :
|
||||
Block::Packet_descriptor::READ;
|
||||
bool succeeded = backend().submit(op, off, dlen, data);
|
||||
|
||||
p->cnt = dlen / backend()->block_size();
|
||||
p->blk = off / backend()->block_size();
|
||||
p->data = data;
|
||||
p->biodone = biodone;
|
||||
p->donearg = donearg;
|
||||
p->sync = !!(op & RUMPUSER_BIO_SYNC);
|
||||
backend()->submit();
|
||||
rumpkern_sched(nlocks, 0);
|
||||
|
||||
if (biodone)
|
||||
biodone(donearg, dlen, succeeded ? 0 : EIO);
|
||||
}
|
||||
|
||||
|
||||
void rump_io_backend_sync()
|
||||
{
|
||||
/* send empty packet with sync request */
|
||||
Packet *p = backend()->alloc();
|
||||
p->cnt = 0;
|
||||
p->sync = true;
|
||||
backend()->submit();
|
||||
backend().sync();
|
||||
}
|
||||
|
||||
|
||||
void rump_io_backend_init()
|
||||
{
|
||||
/* create back end */
|
||||
backend();
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,8 @@ extern "C" {
|
||||
#include <base/lock.h>
|
||||
#include <util/fifo.h>
|
||||
#include <os/timed_semaphore.h>
|
||||
#include <rump/env.h>
|
||||
|
||||
#include "sched.h"
|
||||
|
||||
|
||||
@ -106,7 +108,7 @@ struct rumpuser_mtx
|
||||
|
||||
void rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags)
|
||||
{
|
||||
*mtxp = new(Genode::env()->heap()) rumpuser_mtx(flags);
|
||||
*mtxp = new(Rump::env().heap()) rumpuser_mtx(flags);
|
||||
}
|
||||
|
||||
|
||||
@ -153,7 +155,7 @@ void rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
|
||||
|
||||
void rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
destroy(Genode::env()->heap(), mtx);
|
||||
destroy(Rump::env().heap(), mtx);
|
||||
}
|
||||
|
||||
|
||||
@ -274,13 +276,13 @@ struct rumpuser_cv {
|
||||
|
||||
void rumpuser_cv_init(struct rumpuser_cv **cv)
|
||||
{
|
||||
*cv = new(Genode::env()->heap()) rumpuser_cv();
|
||||
*cv = new(Rump::env().heap()) rumpuser_cv();
|
||||
}
|
||||
|
||||
|
||||
void rumpuser_cv_destroy(struct rumpuser_cv *cv)
|
||||
{
|
||||
destroy(Genode::env()->heap(), cv);
|
||||
destroy(Rump::env().heap(), cv);
|
||||
}
|
||||
|
||||
|
||||
@ -464,7 +466,7 @@ struct rumpuser_rw
|
||||
|
||||
void rumpuser_rw_init(struct rumpuser_rw **rw)
|
||||
{
|
||||
*rw = new(Genode::env()->heap()) rumpuser_rw();
|
||||
*rw = new(Rump::env().heap()) rumpuser_rw();
|
||||
}
|
||||
|
||||
|
||||
@ -531,6 +533,6 @@ void rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rv)
|
||||
|
||||
void rumpuser_rw_destroy(struct rumpuser_rw *rw)
|
||||
{
|
||||
destroy(Genode::env()->heap(), rw);
|
||||
destroy(Rump::env().heap(), rw);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "file_system.h"
|
||||
|
||||
#include <rump/bootstrap.h>
|
||||
#include <rump/env.h>
|
||||
#include <rump_fs/fs.h>
|
||||
#include <util/string.h>
|
||||
#include <util/hard_context.h>
|
||||
@ -76,9 +76,9 @@ static bool check_read_only(Fs_type const &fs_type)
|
||||
}
|
||||
|
||||
|
||||
void File_system::init(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node config)
|
||||
void File_system::init()
|
||||
{
|
||||
Fs_type const fs_type = config.attribute_value("fs", Fs_type());
|
||||
Fs_type const fs_type = Rump::env().config_rom().xml().attribute_value("fs", Fs_type());
|
||||
|
||||
if (!_check_type(fs_type)) {
|
||||
Genode::error("Invalid or no file system given (use \'<config fs=\"<fs type>\"/>)");
|
||||
@ -87,12 +87,8 @@ void File_system::init(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_n
|
||||
}
|
||||
Genode::log("Using ", fs_type, " as file system");
|
||||
|
||||
/* make Genode env and heap known to the rump kernel */
|
||||
rump_bootstrap_init(env, alloc);
|
||||
|
||||
/* start rump kernel */
|
||||
rump_init();
|
||||
|
||||
/* register block device */
|
||||
rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK);
|
||||
|
||||
|
@ -31,7 +31,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
namespace File_system {
|
||||
void init(Genode::Env &, Genode::Allocator &heap, Genode::Xml_node config);
|
||||
void init();
|
||||
bool supports_symlinks();
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "undef.h"
|
||||
|
||||
#include <rump/env.h>
|
||||
#include <rump_fs/fs.h>
|
||||
#include <sys/resource.h>
|
||||
#include "file_system.h"
|
||||
@ -173,7 +174,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
~Session_component()
|
||||
{
|
||||
Dataspace_capability ds = tx_sink()->dataspace();
|
||||
env()->ram_session()->free(static_cap_cast<Ram_dataspace>(ds));
|
||||
Rump::env().env().ram().free(static_cap_cast<Ram_dataspace>(ds));
|
||||
destroy(&_md_alloc, &_root);
|
||||
}
|
||||
|
||||
@ -491,11 +492,13 @@ struct File_system::Main
|
||||
|
||||
Root fs_root { env, sliced_heap };
|
||||
|
||||
Attached_rom_dataspace config { env, "config" };
|
||||
|
||||
Main(Genode::Env &env) : env(env)
|
||||
{
|
||||
File_system::init(env, heap, config.xml());
|
||||
Rump::construct_env(env);
|
||||
|
||||
rump_io_backend_init();
|
||||
|
||||
File_system::init();
|
||||
|
||||
/* set all bits but the stickies */
|
||||
rump_sys_umask(S_ISUID|S_ISGID|S_ISVTX);
|
||||
|
Loading…
x
Reference in New Issue
Block a user