2a2e5c2df4
base generic code: * Remove unused verbosity code from mmio framework * Remove escape sequence end heuristic from LOG * replace Core_console with Core_log (no format specifiers) * move test/printf to test/log * remove `printf()` tests from the log test * check for exact match of the log test output base-fiasco: * remove unused Fiasco::print_l4_threadid function base-nova: * remove unused hexdump utility from core base-hw: * remove unused Kernel::Thread::_print_* debug utilities * always print resource summary of core during startup * remove Kernel::Ipc_node::pd_label (not used anymore) base*: * Turn `printf`,`PWRN`, etc. calls into their log equivalents Ref #1987 Fix #2119
243 lines
5.7 KiB
C++
243 lines
5.7 KiB
C++
/*
|
|
* \brief Fiasco.OC-specific RPC capability factory
|
|
* \author Stefan Kalkowski
|
|
* \author Norman Feske
|
|
* \date 2011-01-13
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2011-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.
|
|
*/
|
|
|
|
/* 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 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 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());
|
|
|
|
// 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 (_md_alloc) 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;
|
|
_pool.apply(cap, [&] (Entry *e) {
|
|
entry = e;
|
|
if (e) {
|
|
_pool.remove(e);
|
|
} else
|
|
warning("Could not find capability to be deleted");
|
|
});
|
|
if (entry) destroy(_md_alloc, entry);
|
|
}
|
|
|
|
|
|
Rpc_cap_factory::~Rpc_cap_factory()
|
|
{
|
|
_pool.remove_all([this] (Entry *e) {
|
|
if (!e) return;
|
|
destroy(_md_alloc, 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;
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
Genode::Cap_index_allocator* cap_idx_alloc()
|
|
{
|
|
static Genode::Cap_index_allocator_tpl<Core_cap_index, 20*1024> _alloc;
|
|
return &_alloc;
|
|
}
|