genode/repos/base-foc/src/core/rpc_cap_factory.cc
Norman Feske aa66b5d62f base: remove dependency from deprecated APIs
This patch adjusts the implementation of the base library and core such
that the code no longer relies on deprecated APIs except for very few
cases, mainly to keep those deprecated APIs in tact for now.

The most prominent changes are:

- Removing the use of base/printf.h

- Removing of the log backend for printf. The 'Console' with the
  format-string parser is still there along with 'snprintf.h' because
  the latter is still used at a few places, most prominently the
  'Connection' classes.

- Removing the notion of a RAM session, which does not exist in
  Genode anymore. Still the types were preserved (by typedefs to
  PD session) to keep up compatibility. But this transition should
  come to an end now.

- Slight rennovation of core's tracing service, e.g., the use of an
  Attached_dataspace as the Argument_buffer.

- Reducing the reliance on global accessors like deprecated_env() or
  core_env(). Still there is a longish way to go to eliminate all such
  calls. A useful pattern (or at least a stop-gap solution) is to
  pass the 'Env' to the individual compilation units via init functions.

- Avoiding the use of the old 'Child_policy::resolve_session_request'
  interface that returned a 'Service' instead of a 'Route'.

Issue #1987
2019-02-19 11:08:17 +01:00

236 lines
5.6 KiB
C++

/*
* \brief Fiasco.OC-specific RPC capability factory
* \author Stefan Kalkowski
* \author Norman Feske
* \date 2011-01-13
*/
/*
* Copyright (C) 2011-2017 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.
*/
/* Genode includes */
#include <base/capability.h>
#include <util/misc_math.h>
/* core includes */
#include <rpc_cap_factory.h>
#include <cap_id_alloc.h>
#include <cap_index.h>
#include <platform.h>
/* base-internal includes */
#include <base/internal/cap_alloc.h>
#include <base/internal/foc_assert.h>
/* Fiasco includes */
namespace Fiasco {
#include <l4/sys/consts.h>
#include <l4/sys/debugger.h>
#include <l4/sys/factory.h>
#include <l4/sys/task.h>
#include <l4/sys/types.h>
}
using namespace Genode;
/***************************
** Cap_index_allocator **
***************************/
Genode::Cap_index_allocator &Genode::cap_idx_alloc()
{
static Genode::Cap_index_allocator_tpl<Core_cap_index,10*1024> alloc;
return alloc;
}
/*******************
** Cap_mapping **
*******************/
Core_cap_index *Cap_mapping::_get_cap()
{
int const id = platform_specific().cap_id_alloc().alloc();
return static_cast<Core_cap_index*>(cap_map().insert(id));
}
void Cap_mapping::map(Fiasco::l4_cap_idx_t task)
{
using namespace Fiasco;
if (!local.valid() || !Fiasco::Capability::valid(remote))
return;
l4_msgtag_t tag = l4_task_map(task, L4_BASE_TASK_CAP,
l4_obj_fpage(local.data()->kcap(), 0, L4_FPAGE_RWX),
((l4_cap_idx_t)remote) | L4_ITEM_MAP);
if (l4_msgtag_has_error(tag))
error("mapping cap failed");
}
Cap_mapping::Cap_mapping(bool alloc, Fiasco::l4_cap_idx_t r)
: local(alloc ? _get_cap() : (Native_capability::Data *)nullptr), remote(r) { }
Cap_mapping::Cap_mapping(Native_capability cap, Fiasco::l4_cap_idx_t r)
: local(cap), remote(r) { }
/***********************
** Rpc_cap_factory **
***********************/
Native_capability Rpc_cap_factory::alloc(Native_capability ep)
{
Native_capability cap;
if (!ep.valid()) {
warning("Invalid reference capability!");
return cap;
}
try {
using namespace Fiasco;
Core_cap_index const * ref = static_cast<Core_cap_index const*>(ep.data());
ASSERT(ref && ref->pt(), "No valid platform_thread");
/*
* Allocate new id, and ipc-gate and set id as gate-label
*/
unsigned long const id = platform_specific().cap_id_alloc().alloc();
Core_cap_index *idx = static_cast<Core_cap_index*>(cap_map().insert(id));
if (!idx) {
warning("Out of capability indices!");
platform_specific().cap_id_alloc().free(id);
return cap;
}
l4_msgtag_t tag = l4_factory_create_gate(L4_BASE_FACTORY_CAP,
idx->kcap(),
ref->pt()->thread().local.data()->kcap(), id);
if (l4_msgtag_has_error(tag)) {
error("l4_factory_create_gate failed!");
cap_map().remove(idx);
platform_specific().cap_id_alloc().free(id);
return cap;
} else
/* set debugger-name of ipc-gate to thread's name */
Fiasco::l4_debugger_set_object_name(idx->kcap(), ref->pt()->name().string());
// XXX remove cast
idx->session((Pd_session_component *)this);
idx->pt(ref->pt());
cap = Native_capability(idx);
} catch (Cap_id_allocator::Out_of_ids) {
error("out of capability IDs");
}
/*
* insert valid capabilities into the session's object pool to
* be able to destroy them on session destruction.
* For the construction of core's own threads the related cap session
* doesn't have an allocator set. But this session gets never destroyed
* so this is not an issue.
*/
if (cap.valid())
_pool.insert(new (_entry_slab) Entry(cap));
return cap;
}
void Rpc_cap_factory::free(Native_capability cap)
{
using namespace Fiasco;
if (!cap.valid()) return;
/* check whether the capability was created by this cap_session */
if (static_cast<Core_cap_index const *>(cap.data())->session() != (Pd_session_component *)this)
return;
Entry * entry = nullptr;
_pool.apply(cap, [&] (Entry *e) {
entry = e;
if (e) {
_pool.remove(e);
} else
warning("Could not find capability to be deleted");
});
if (entry) destroy(_entry_slab, entry);
}
Rpc_cap_factory::~Rpc_cap_factory()
{
_pool.remove_all([this] (Entry *e) {
if (!e) return;
destroy(_entry_slab, e);
});
}
/*******************************
** Capability ID Allocator **
*******************************/
Cap_id_allocator::Cap_id_allocator(Allocator &alloc)
: _id_alloc(&alloc)
{
_id_alloc.add_range(CAP_ID_OFFSET, CAP_ID_RANGE);
}
unsigned long Cap_id_allocator::alloc()
{
Lock::Guard lock_guard(_lock);
void *id = nullptr;
if (_id_alloc.alloc(CAP_ID_OFFSET, &id))
return (unsigned long) id;
throw Out_of_ids();
}
void Cap_id_allocator::free(unsigned long id)
{
Lock::Guard lock_guard(_lock);
if (id < CAP_ID_RANGE)
_id_alloc.free((void*)(id & CAP_ID_MASK), CAP_ID_OFFSET);
}
void Genode::Capability_map::remove(Genode::Cap_index *i)
{
using namespace Genode;
using namespace Fiasco;
Lock_guard<Spin_lock> guard(_lock);
if (i) {
Core_cap_index* e = static_cast<Core_cap_index*>(_tree.first() ? _tree.first()->find_by_id(i->id()) : 0);
if (e == i) {
l4_msgtag_t tag = l4_task_unmap(L4_BASE_TASK_CAP,
l4_obj_fpage(i->kcap(), 0, L4_FPAGE_RWX),
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
if (l4_msgtag_has_error(tag))
error("destruction of ipc-gate ", i->kcap(), " failed!");
platform_specific().cap_id_alloc().free(i->id());
_tree.remove(i);
}
cap_idx_alloc().free(i, 1);
}
}