2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Fiasco protection domain facility
|
|
|
|
* \author Christian Helmuth
|
|
|
|
* \date 2006-04-11
|
|
|
|
*
|
|
|
|
* On Fiasco, the pd class has several duties:
|
|
|
|
*
|
|
|
|
* - It is an allocator for L4 tasks and cares for versioning and recycling. We
|
|
|
|
* do this with "static class members".
|
|
|
|
* - L4 threads are tied to L4 tasks and there are only 128 per L4 task. So
|
|
|
|
* each pd object is an allocator for its threads.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2006-2017 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
2016-06-13 13:53:58 +02:00
|
|
|
#include <base/native_capability.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* core includes */
|
|
|
|
#include <util.h>
|
|
|
|
#include <platform_pd.h>
|
|
|
|
|
|
|
|
/* Fiasco includes */
|
|
|
|
namespace Fiasco {
|
|
|
|
#include <l4/sys/syscalls.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace Fiasco;
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
** Static class members **
|
|
|
|
**************************/
|
|
|
|
|
|
|
|
static bool _init = false;
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::init()
|
|
|
|
{
|
|
|
|
if (_init) return;
|
|
|
|
|
|
|
|
unsigned i;
|
|
|
|
Pd_alloc reserved(true, true, 0);
|
|
|
|
Pd_alloc free(false, true, 0);
|
|
|
|
|
|
|
|
/* mark reserved protection domains */
|
|
|
|
for (i = 0; i < PD_FIRST; ++i) _pds()[i] = reserved;
|
|
|
|
/* init remainder */
|
|
|
|
for ( ; i < PD_MAX; ++i) _pds()[i] = free;
|
|
|
|
|
|
|
|
_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************
|
|
|
|
** Private object members **
|
|
|
|
****************************/
|
|
|
|
|
|
|
|
void Platform_pd::_create_pd(bool syscall)
|
|
|
|
{
|
|
|
|
l4_threadid_t l4t = l4_myself();
|
|
|
|
l4t.id.task = _pd_id;
|
|
|
|
l4t.id.lthread = 0;
|
|
|
|
l4t.id.version_low = _version;
|
|
|
|
|
|
|
|
l4_taskid_t nt;
|
|
|
|
if (syscall)
|
|
|
|
nt = l4_task_new(l4t, 0, 0, 0, l4t);
|
|
|
|
else
|
|
|
|
nt = l4t;
|
|
|
|
|
|
|
|
if (l4_is_nil_id(nt))
|
|
|
|
panic("pd creation failed");
|
|
|
|
|
|
|
|
_l4_task_id = nt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::_destroy_pd()
|
|
|
|
{
|
|
|
|
l4_threadid_t l4t = _l4_task_id;
|
|
|
|
|
|
|
|
/* L4 task deletion is: make inactive with myself as chief in 2nd parameter */
|
|
|
|
l4_taskid_t nt = l4_task_new(l4t, convert_native_thread_id_to_badge(l4_myself()),
|
|
|
|
0, 0, L4_NIL_ID);
|
|
|
|
|
|
|
|
if (l4_is_nil_id(nt))
|
|
|
|
panic("pd destruction failed");
|
|
|
|
|
|
|
|
_l4_task_id = L4_INVALID_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Platform_pd::_alloc_pd(signed pd_id)
|
|
|
|
{
|
|
|
|
if (pd_id == PD_INVALID) {
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = PD_FIRST; i < PD_MAX; i++)
|
|
|
|
if (_pds()[i].free) break;
|
|
|
|
|
|
|
|
/* no free protection domains available */
|
|
|
|
if (i == PD_MAX) return -1;
|
|
|
|
|
|
|
|
pd_id = i;
|
|
|
|
} else {
|
|
|
|
if (!_pds()[pd_id].reserved || !_pds()[pd_id].free)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_pds()[pd_id].free = 0;
|
|
|
|
|
|
|
|
_pd_id = pd_id;
|
|
|
|
_version = _pds()[pd_id].version;
|
|
|
|
|
|
|
|
return pd_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::_free_pd()
|
|
|
|
{
|
|
|
|
unsigned t = _pd_id;
|
|
|
|
|
|
|
|
/* XXX check and log double-free? */
|
|
|
|
if (_pds()[t].free) return;
|
|
|
|
|
|
|
|
/* maximum reuse count reached leave non-free */
|
|
|
|
if (_pds()[t].version == PD_VERSION_MAX) return;
|
|
|
|
|
|
|
|
_pds()[t].free = 1;
|
|
|
|
++_pds()[t].version;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::_init_threads()
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = 0; i < THREAD_MAX; ++i)
|
|
|
|
_threads[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Platform_thread* Platform_pd::_next_thread()
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
/* look for bound thread */
|
|
|
|
for (i = 0; i < THREAD_MAX; ++i)
|
|
|
|
if (_threads[i]) break;
|
|
|
|
|
|
|
|
/* no bound threads */
|
|
|
|
if (i == THREAD_MAX) return 0;
|
|
|
|
|
|
|
|
return _threads[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Platform_pd::_alloc_thread(int thread_id, Platform_thread *thread)
|
|
|
|
{
|
|
|
|
int i = thread_id;
|
|
|
|
|
|
|
|
/* look for free thread */
|
|
|
|
if (thread_id == Platform_thread::THREAD_INVALID) {
|
|
|
|
for (i = 0; i < THREAD_MAX; ++i)
|
|
|
|
if (!_threads[i]) break;
|
|
|
|
|
|
|
|
/* no free threads available */
|
|
|
|
if (i == THREAD_MAX) return -1;
|
|
|
|
} else {
|
|
|
|
if (_threads[i]) return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
_threads[i] = thread;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::_free_thread(int thread_id)
|
|
|
|
{
|
|
|
|
if (!_threads[thread_id])
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
warning("double-free of thread ", Hex(_pd_id), ".", Hex(thread_id), " detected");
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
_threads[thread_id] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************
|
|
|
|
** Public object members **
|
|
|
|
***************************/
|
|
|
|
|
2016-04-20 21:12:57 +02:00
|
|
|
bool Platform_pd::bind_thread(Platform_thread *thread)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
/* thread_id is THREAD_INVALID by default - only core is the special case */
|
|
|
|
int thread_id = thread->thread_id();
|
|
|
|
l4_threadid_t l4_thread_id;
|
|
|
|
|
|
|
|
int t = _alloc_thread(thread_id, thread);
|
|
|
|
if (t < 0) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
error("thread alloc failed");
|
2016-04-20 21:12:57 +02:00
|
|
|
return false;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
thread_id = t;
|
|
|
|
|
|
|
|
l4_thread_id = _l4_task_id;
|
|
|
|
l4_thread_id.id.lthread = thread_id;
|
|
|
|
|
|
|
|
/* finally inform thread about binding */
|
|
|
|
thread->bind(thread_id, l4_thread_id, this);
|
|
|
|
|
2016-04-20 21:12:57 +02:00
|
|
|
return true;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_pd::unbind_thread(Platform_thread *thread)
|
|
|
|
{
|
|
|
|
int thread_id = thread->thread_id();
|
|
|
|
|
|
|
|
/* unbind thread before proceeding */
|
|
|
|
thread->unbind();
|
|
|
|
|
|
|
|
_free_thread(thread_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-05 08:50:16 +02:00
|
|
|
Platform_pd::Platform_pd(Allocator * md_alloc, char const *,
|
|
|
|
signed pd_id, bool create)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
/* check correct init */
|
|
|
|
if (!_init)
|
|
|
|
panic("init pd facility via Platform_pd::init() before using it!");
|
|
|
|
|
|
|
|
/* init threads */
|
|
|
|
_init_threads();
|
|
|
|
|
|
|
|
int ret = _alloc_pd(pd_id);
|
|
|
|
if (ret < 0) {
|
|
|
|
panic("pd alloc failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
_create_pd(create);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Platform_pd::~Platform_pd()
|
|
|
|
{
|
2015-07-02 11:52:57 +02:00
|
|
|
/* invalidate weak pointers to this object */
|
|
|
|
Address_space::lock_for_destruction();
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/* unbind all threads */
|
|
|
|
while (Platform_thread *t = _next_thread()) unbind_thread(t);
|
|
|
|
|
|
|
|
_destroy_pd();
|
|
|
|
_free_pd();
|
|
|
|
}
|
|
|
|
|