2014-04-09 15:24:55 +02:00
|
|
|
/*
|
|
|
|
* \brief Virtualbox adjusted pthread_create implementation
|
|
|
|
* \author Alexander Boettcher
|
|
|
|
* \date 2014-04-09
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is distributed under the terms of the GNU General Public License
|
|
|
|
* version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode */
|
|
|
|
#include <base/printf.h>
|
|
|
|
#include <base/thread.h>
|
|
|
|
#include <base/env.h>
|
2014-05-23 09:26:57 +02:00
|
|
|
#include <cpu_session/connection.h>
|
2014-04-09 15:24:55 +02:00
|
|
|
|
|
|
|
/* Genode libc pthread binding */
|
|
|
|
#include "thread.h"
|
|
|
|
|
2014-07-16 21:43:41 +02:00
|
|
|
#include "sup.h"
|
|
|
|
|
2014-04-09 15:24:55 +02:00
|
|
|
/* libc */
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
/* vbox */
|
|
|
|
#include <internal/thread.h>
|
|
|
|
|
2014-05-23 09:26:57 +02:00
|
|
|
static Genode::Cpu_session * get_cpu_session(RTTHREADTYPE type) {
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
static Cpu_connection * con[RTTHREADTYPE_END - 1];
|
|
|
|
static Lock lock;
|
|
|
|
|
|
|
|
Assert(type && type < RTTHREADTYPE_END);
|
|
|
|
|
|
|
|
Lock::Guard guard(lock);
|
|
|
|
|
|
|
|
if (con[type - 1])
|
|
|
|
return con[type - 1];
|
|
|
|
|
|
|
|
long const prio = (RTTHREADTYPE_END - type) *
|
|
|
|
(Cpu_session::PRIORITY_LIMIT / RTTHREADTYPE_END);
|
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
char * data = new (env()->heap()) char[16];
|
2014-05-23 09:26:57 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
snprintf(data, 16, "vbox %u", type);
|
2014-05-23 09:26:57 +02:00
|
|
|
|
|
|
|
con[type - 1] = new (env()->heap()) Cpu_connection(data, prio);
|
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
/* upgrade memory of cpu session for frequent used thread type */
|
|
|
|
if (type == RTTHREADTYPE_IO)
|
|
|
|
Genode::env()->parent()->upgrade(con[type - 1]->cap(), "ram_quota=4096");
|
|
|
|
|
2014-05-23 09:26:57 +02:00
|
|
|
return con[type - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|
|
|
void *(*start_routine) (void *), void *arg)
|
|
|
|
{
|
|
|
|
PRTTHREADINT rtthread = reinterpret_cast<PRTTHREADINT>(arg);
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
Assert(rtthread);
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
size_t stack_size = Genode::Native_config::context_virtual_size() -
|
|
|
|
sizeof(Genode::Native_utcb) - 2 * (1UL << 12);
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
if (rtthread->cbStack < stack_size)
|
|
|
|
stack_size = rtthread->cbStack;
|
|
|
|
else
|
|
|
|
PWRN("requested stack for thread '%s' of %zu Bytes is too large, "
|
|
|
|
"limit to %zu Bytes", rtthread->szName, rtthread->cbStack,
|
|
|
|
stack_size);
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
/* sanity check - emt and vcpu thread have to have same prio class */
|
|
|
|
if (!Genode::strcmp(rtthread->szName, "EMT"))
|
|
|
|
Assert(rtthread->enmType == RTTHREADTYPE_EMULATION);
|
2014-05-23 09:26:57 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
if (rtthread->enmType == RTTHREADTYPE_EMULATION) {
|
|
|
|
Genode::Cpu_session * cpu_session = get_cpu_session(RTTHREADTYPE_EMULATION);
|
|
|
|
/*
|
|
|
|
Genode::Affinity::Space cpu_space = cpu_session->affinity_space();
|
|
|
|
Genode::Affinity::Location location = cpu_space.location_of_index(i);
|
|
|
|
*/
|
|
|
|
Genode::Affinity::Location location;
|
|
|
|
if (create_emt_vcpu(thread, stack_size, attr, start_routine, arg,
|
|
|
|
cpu_session, location))
|
|
|
|
return 0;
|
|
|
|
/* no haredware support, create normal pthread thread */
|
|
|
|
}
|
2014-05-23 09:26:57 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
pthread_t thread_obj = new (Genode::env()->heap())
|
|
|
|
pthread(attr ? *attr : 0, start_routine,
|
|
|
|
arg, stack_size, rtthread->szName,
|
|
|
|
get_cpu_session(rtthread->enmType));
|
2014-04-24 10:55:09 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
if (!thread_obj)
|
|
|
|
return EAGAIN;
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
*thread = thread_obj;
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
thread_obj->start();
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-04-09 15:24:55 +02:00
|
|
|
|
2014-09-23 13:01:47 +02:00
|
|
|
extern "C" int pthread_attr_setdetachstate(pthread_attr_t *, int)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int pthread_attr_setstacksize(pthread_attr_t *, size_t)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int pthread_atfork(void (*)(void), void (*)(void), void (*)(void))
|
|
|
|
{
|
|
|
|
return 0;
|
2014-04-09 15:24:55 +02:00
|
|
|
}
|