genode/ports/src/noux/cpu_session_component.h

141 lines
3.9 KiB
C++

/*
* \brief CPU session provided to Noux processes
* \author Norman Feske
* \date 2012-02-22
*
* The custom implementation of the CPU session interface is used to tweak
* the startup procedure as performed by the 'Process' class. Normally,
* processes start execution immediately at creation time at the ELF entry
* point. For implementing fork semantics, however, this default behavior
* does not work. Instead, we need to defer the start of the main thread
* until we have finished copying the address space of the forking process.
* Furthermore, we need to start the main thread at a custom trampoline
* function rather than at the ELF entry point. Those customizations are
* possible by wrapping core's CPU service.
*/
/*
* Copyright (C) 2012-2013 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 _NOUX__CPU_SESSION_COMPONENT_H_
#define _NOUX__CPU_SESSION_COMPONENT_H_
/* Genode includes */
#include <base/rpc_server.h>
#include <cpu_session/connection.h>
namespace Noux {
using namespace Genode;
class Cpu_session_component : public Rpc_object<Cpu_session>
{
private:
bool const _forked;
Cpu_connection _cpu;
Thread_capability _main_thread;
public:
/**
* Constructor
*
* \param forked false if the CPU session belongs to a child
* created via execve or to the init process, or
* true if the CPU session belongs to a newly forked
* process.
*
* The 'forked' parameter controls the policy applied to the
* startup of the main thread.
*/
Cpu_session_component(char const *label, bool forked)
: _forked(forked), _cpu(label) { }
/**
* Explicitly start main thread, only meaningful when
* 'forked' is true
*/
void start_main_thread(addr_t ip, addr_t sp)
{
_cpu.start(_main_thread, ip, sp);
}
Cpu_session_capability cpu_cap() { return _cpu.cap(); }
/***************************
** Cpu_session interface **
***************************/
Thread_capability create_thread(Name const &name, addr_t utcb)
{
/*
* Prevent any attempt to create more than the main
* thread.
*/
if (_main_thread.valid()) {
PWRN("Invalid attempt to create a thread besides main");
while (1);
return Thread_capability();
}
_main_thread = _cpu.create_thread(name, utcb);
PINF("created main thread");
return _main_thread;
}
Ram_dataspace_capability utcb(Thread_capability thread) {
return _cpu.utcb(thread); }
void kill_thread(Thread_capability thread) {
_cpu.kill_thread(thread); }
int set_pager(Thread_capability thread,
Pager_capability pager) {
return _cpu.set_pager(thread, pager); }
int start(Thread_capability thread, addr_t ip, addr_t sp)
{
if (_forked) {
PINF("defer attempt to start thread at ip 0x%lx", ip);
return 0;
}
return _cpu.start(thread, ip, sp);
}
void pause(Thread_capability thread) {
_cpu.pause(thread); }
void resume(Thread_capability thread) {
_cpu.resume(thread); }
void cancel_blocking(Thread_capability thread) {
_cpu.cancel_blocking(thread); }
Thread_state state(Thread_capability thread) {
return _cpu.state(thread); }
void state(Thread_capability thread, Thread_state const &state) {
_cpu.state(thread, state); }
void exception_handler(Thread_capability thread,
Signal_context_capability handler) {
_cpu.exception_handler(thread, handler); }
void single_step(Thread_capability thread, bool enable) {
_cpu.single_step(thread, enable); }
Affinity::Space affinity_space() const {
return _cpu.affinity_space(); }
void affinity(Thread_capability thread, Affinity::Location location) {
_cpu.affinity(thread, location); }
};
}
#endif /* _NOUX__CPU_SESSION_COMPONENT_H_ */