Hi Daniel,

that's right we doesn't pass the scheduler capability to any children.
This is an security issue, if you simply pass the kernel's scheduler
capability into each task, they could interfere with a global scheduling
strategy.

To circumvent this, there are two possibilities: One could put a virtual
scheduler object's capability into the designated
'L4_BASE_SCHEDULER_CAP' capability slot of each task. I guess this is
the L4re way of confining the scheduling facilities of tasks.
The more Genode-like way, that Norman already proposed to you, is to
extend the CPU-session interface, e.g. by an additional 'migrate' or
'affinity' method, so that the kernel's scheduler capability further
resides in core, and you can use a kernel-independent interface for
load-balancing on different CPU's or cores.

I would advise you against mapping the scheduler's capability from core
to its children, even when hacking up a prototype or example. It's
probably not easier than extending the cpu-session interface. To use the
scheduler for distributing threads on different cores you need in
addition to the scheduler's capability the capability of each thread you
like to migrate, but these also reside in the 'core' task only.

I've produced a small patch for you, that extends the cpu-session
interface (for the Fiasco.OC platform only) by a 'migrate' function,
which doesn't do any real work - it's just a skeleton.
Of course, we will also provide a kernel independent solution for SMP in
the future, but if you want to get hands on experience with SMP and
Genode/Fiasco.OC now, this might help you as a starting point.

with best regards
Stefan

On 03/19/2011 01:29 AM, Daniel Waddington wrote:
> Hi,
> I'm trying to put in some temporary feature in Genode to set the
> affinity of threads.  In Genode the scheduler capability
> (L4_BASE_SCHEDULER_CAP) doesn't seem to be passed from the core to the
> children.  Is there any obvious way to do this with the existing Genode
> implementation - we can hack up a solution but I wanted to check first.
> 
> Thanks
> Daniel
> 
> 
> 
> ------------------------------------------------------------------------------
> Colocation vs. Managed Hosting
> A question and answer guide to determining the best fit
> for your organization - today and in the future.
> http://p.sf.net/sfu/internap-sfd2d
> 
> 
> 
> _______________________________________________
> Genode-main mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/genode-main

-- 
Stefan Kalkowski
Genode Labs

http://www.genode-labs.com/ · http://genode.org/

Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Index: base-foc/include/cpu_session/cpu_session.h
===================================================================
--- base-foc/include/cpu_session/cpu_session.h	(revision 0)
+++ base-foc/include/cpu_session/cpu_session.h	(revision 0)
@@ -0,0 +1,177 @@
+/*
+ * \brief  CPU (processing time) manager session interface
+ * \author Christian Helmuth
+ * \date   2006-06-27
+ *
+ * :Question:
+ *
+ *   Why are thread operations not methods of the thread but
+ *   methods of the CPU session?
+ *
+ * :Answer:
+ *
+ *   This enables the CPU session to impose policies on thread
+ *   operations. These policies are based on the session
+ *   construction arguments. If thread operations would be
+ *   provided as thread methods, Thread would need to consult
+ *   its container object (its CPU session) about the authorization
+ *   of each operation and, thereby, would introduce a circular
+ *   dependency between CPU session and Thread.
+ */
+
+/*
+ * Copyright (C) 2006-2011 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 _INCLUDE__CPU_SESSION__CPU_SESSION_H_
+#define _INCLUDE__CPU_SESSION__CPU_SESSION_H_
+
+#include <base/stdint.h>
+#include <base/exception.h>
+#include <base/thread_state.h>
+#include <thread/capability.h>
+#include <pager/capability.h>
+
+namespace Genode {
+
+	class Cpu_session
+	{
+		protected:
+
+			enum Opcode {
+				CREATE_THREAD, KILL_THREAD, FIRST, NEXT, SET_PAGER, START,
+				CANCEL_BLOCKING, NAME, STATE, MIGRATE
+			};
+
+		public:
+
+			/*********************
+			 ** Exception types **
+			 *********************/
+
+			class Thread_creation_failed : public Exception { };
+
+			static const char *service_name() { return "CPU"; }
+
+			enum { THREAD_NAME_LEN = 32 };
+			enum { PRIORITY_LIMIT = 1 << 16 };
+			enum { DEFAULT_PRIORITY = 0 };
+
+			virtual ~Cpu_session() { }
+
+			/**
+			 * Create a new thread
+			 *
+			 * \param   name  name for the thread
+			 * \return        capability representing the new thread
+			 * \throw         Thread_creation_failed
+			 */
+			virtual Thread_capability create_thread(const char *name) = 0;
+
+			/**
+			 * Kill an existing thread
+			 *
+			 * \param thread  capability of the thread to kill
+			 */
+			virtual void kill_thread(Thread_capability thread) = 0;
+
+			/**
+			 * Retrieve thread list of CPU session
+			 *
+			 * The next() function returns an invalid capability if the
+			 * specified thread does not exists or if it is the last one
+			 * of the CPU session.
+			 */
+			virtual Thread_capability first() = 0;
+			virtual Thread_capability next(Thread_capability curr) = 0;
+
+			/**
+			 * Set paging capabilities for thread
+			 *
+			 * \param thread  thread to configure
+			 * \param pager   capability used to propagate page faults
+			 */
+			virtual int set_pager(Thread_capability thread,
+			                      Pager_capability  pager) = 0;
+
+			/**
+			 * Modify instruction and stack pointer of thread - start the
+			 * thread
+			 *
+			 * \param thread  thread to start
+			 * \param ip      initial instruction pointer
+			 * \param sp      initial stack pointer
+			 *
+			 * \return        0 on success
+			 */
+			virtual int start(Thread_capability thread, addr_t ip, addr_t sp) = 0;
+
+			/**
+			 * Cancel a currently blocking operation
+			 *
+			 * \param thread  thread to unblock
+			 */
+			virtual void cancel_blocking(Thread_capability thread) = 0;
+
+			/**
+			 * Return thread name
+			 *
+			 * \param thread    thread to query
+			 * \param name_dst  destination string buffer
+			 * \param name_len  length of destination string buffer
+			 *
+			 * \return          0 on success
+			 */
+			virtual int name(Thread_capability thread,
+			                 char *name_dst, size_t name_len) = 0;
+
+			/**
+			 * Return thread state
+			 *
+			 * \param thread     thread to spy on
+			 * \param state_dst  result
+			 *
+			 * \return           0 on success
+			 */
+			virtual int state(Thread_capability thread,
+			                  Thread_state *state_dst) = 0;
+
+			virtual int migrate(Thread_capability thread, unsigned cpu) = 0;
+
+
+			/**
+			 * Translate generic priority value to kernel-specific priority levels
+			 *
+			 * \param pf_prio_limit  maximum priority used for the kernel, must
+			 *                       be power of 2
+			 * \param prio           generic priority value as used by the CPU
+			 *                       session interface
+			 * \param inverse        order of platform priorities, if true
+			 *                       'pf_prio_limit' corresponds to the highest
+			 *                       priority, otherwise it refers to the
+			 *                       lowest priority.
+			 * \return               platform-specific priority value
+			 */
+			static unsigned scale_priority(unsigned pf_prio_limit, unsigned prio,
+			                               bool inverse = true)
+			{
+				/* if no priorities are used, use the platform priority limit */
+				if (prio == 0) return pf_prio_limit;
+
+				/*
+				 * Generic priority values are (0 is highest, 'PRIORITY_LIMIT'
+				 * is lowest. On platforms where priority levels are defined
+				 * the other way round, we have to invert the priority value.
+				 */
+				prio = inverse ? Cpu_session::PRIORITY_LIMIT - prio : prio;
+
+				/* scale value to platform priority range 0..pf_prio_limit */
+				return (prio*pf_prio_limit)/Cpu_session::PRIORITY_LIMIT;
+			}
+	};
+}
+
+#endif /* _INCLUDE__CPU_SESSION__CPU_SESSION_H_ */
Index: base-foc/include/cpu_session/client.h
===================================================================
--- base-foc/include/cpu_session/client.h	(revision 0)
+++ base-foc/include/cpu_session/client.h	(revision 0)
@@ -0,0 +1,117 @@
+/*
+ * \brief  Client-side cpu session interface
+ * \author Christian Helmuth
+ * \date   2006-07-12
+ */
+
+/*
+ * Copyright (C) 2006-2011 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 _INCLUDE__CPU_SESSION__CLIENT_H_
+#define _INCLUDE__CPU_SESSION__CLIENT_H_
+
+#include <cpu_session/capability.h>
+#include <base/ipc.h>
+#include <base/lock.h>
+
+namespace Genode {
+
+	class Cpu_session_client : public Cpu_session
+	{
+		private:
+
+			Msgbuf<THREAD_NAME_LEN + 64> _snd_msg, _rcv_msg;
+			Ipc_client                   _ipc_client;
+			Lock                         _lock;
+
+		public:
+
+			explicit Cpu_session_client(Cpu_session_capability session)
+			: _ipc_client(session, &_snd_msg, &_rcv_msg) { }
+
+			Thread_capability create_thread(const char* name)
+			{
+				Lock::Guard lock_guard(_lock);
+				Thread_capability result;
+
+				switch (_ipc_client << CREATE_THREAD << Buffer(name)
+				                    << IPC_CALL
+				                    >> result) {
+
+				case -1: throw Thread_creation_failed();
+				default: break;
+				}
+
+				return result;
+			}
+
+			void kill_thread(Thread_capability thread)
+			{
+				Lock::Guard lock_guard(_lock);
+				_ipc_client << KILL_THREAD << thread << IPC_CALL;
+			}
+
+			Thread_capability first()
+			{
+				Lock::Guard lock_guard(_lock);
+				Thread_capability result;
+				_ipc_client << FIRST << IPC_CALL >> result;
+				return result;
+			}
+
+			Thread_capability next(Thread_capability curr)
+			{
+				Lock::Guard lock_guard(_lock);
+				Thread_capability result;
+				_ipc_client << NEXT << curr << IPC_CALL >> result;
+				return result;
+			}
+
+			int set_pager(Thread_capability thread, Pager_capability pager)
+			{
+				Lock::Guard lock_guard(_lock);
+				return (_ipc_client << SET_PAGER << thread << pager
+				                    << IPC_CALL);
+			}
+
+			int start(Thread_capability thread, addr_t ip, addr_t sp)
+			{
+				Lock::Guard lock_guard(_lock);
+				return (_ipc_client << START << thread << ip << sp
+				                    << IPC_CALL);
+			}
+
+			void cancel_blocking(Thread_capability thread)
+			{
+				Lock::Guard lock_guard(_lock);
+				_ipc_client << CANCEL_BLOCKING << thread << IPC_CALL;
+			}
+
+			int name(Thread_capability thread, char *name_dst, size_t name_len)
+			{
+				Lock::Guard lock_guard(_lock);
+				Buffer name;
+				int res = _ipc_client << NAME << thread << IPC_CALL >> name;
+				strncpy(name_dst, name.addr(), name_len);
+				return res;
+			}
+
+			int state(Thread_capability thread, Thread_state *dst_state)
+			{
+				Lock::Guard lock_guard(_lock);
+				return (_ipc_client << STATE << thread << IPC_CALL >> *dst_state);
+			}
+
+			int migrate(Thread_capability thread, unsigned cpu)
+			{
+				Lock::Guard lock_guard(_lock);
+				return (_ipc_client << MIGRATE << thread << cpu << IPC_CALL);
+			}
+	};
+}
+
+#endif /* _INCLUDE__CPU_SESSION__CLIENT_H_ */
Index: base-foc/include/cpu_session/connection.h
===================================================================
--- base-foc/include/cpu_session/connection.h	(revision 0)
+++ base-foc/include/cpu_session/connection.h	(revision 0)
@@ -0,0 +1,44 @@
+/*
+ * \brief  Connection to RAM service
+ * \author Norman Feske
+ * \date   2008-08-22
+ */
+
+/*
+ * Copyright (C) 2008-2011 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 _INCLUDE__CPU_SESSION__CONNECTION_H_
+#define _INCLUDE__CPU_SESSION__CONNECTION_H_
+
+#include <cpu_session/client.h>
+#include <base/connection.h>
+
+namespace Genode {
+
+	class Cpu_connection : public Connection<Cpu_session_capability>,
+	                       public Cpu_session_client
+	{
+		public:
+
+			/**
+			 * Constructor
+			 *
+			 * \param label     initial session label
+			 * \param priority  designated priority of all threads created
+			 *                  with this CPU session
+			 */
+			Cpu_connection(const char *label = "", long priority = DEFAULT_PRIORITY)
+			:
+				Connection<Cpu_session_capability>(
+					session(service_name(),
+					        "priority=0x%lx, ram_quota=32K, label=\"%s\"",
+					        priority, label)),
+				Cpu_session_client(cap()) { }
+	};
+}
+
+#endif /* _INCLUDE__CPU_SESSION__CONNECTION_H_ */
Index: base-foc/include/cpu_session/capability.h
===================================================================
--- base-foc/include/cpu_session/capability.h	(revision 0)
+++ base-foc/include/cpu_session/capability.h	(revision 0)
@@ -0,0 +1,22 @@
+/*
+ * \brief  CPU-session capability type
+ * \author Norman Feske
+ * \date   2008-08-16
+ */
+
+/*
+ * Copyright (C) 2008-2011 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 _INCLUDE__CPU_SESSION__CAPABILITY_H_
+#define _INCLUDE__CPU_SESSION__CAPABILITY_H_
+
+#include <session/capability.h>
+#include <cpu_session/cpu_session.h>
+
+namespace Genode { typedef Typed_capability<Cpu_session, Session_capability> Cpu_session_capability; }
+
+#endif /* _INCLUDE__CPU_SESSION__CAPABILITY_H_ */
Index: base-foc/include/cpu_session/server.h
===================================================================
--- base-foc/include/cpu_session/server.h	(revision 0)
+++ base-foc/include/cpu_session/server.h	(revision 0)
@@ -0,0 +1,133 @@
+/*
+ * \brief  Server-side de-marshaller of cpu session interface
+ * \author Christian Helmuth
+ * \date   2006-07-12
+ */
+
+/*
+ * Copyright (C) 2006-2011 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 _INCLUDE__CPU_SESSION__SERVER_H_
+#define _INCLUDE__CPU_SESSION__SERVER_H_
+
+#include <base/server.h>
+#include <cpu_session/cpu_session.h>
+#include <base/printf.h>
+
+namespace Genode {
+
+	class Cpu_session_server : public Server_object, public Cpu_session
+	{
+		public:
+
+			int dispatch(int op, Ipc_istream &is, Ipc_ostream &os)
+			{
+				switch (op) {
+
+				case CREATE_THREAD:
+					{
+						Buffer name;
+
+						is >> name;
+						try {
+							os << create_thread(name.addr());
+							return 0;
+
+						} catch (Thread_creation_failed) {
+							os << Thread_capability();
+							return -1;
+						}
+					}
+
+				case KILL_THREAD:
+					{
+						Thread_capability thread;
+
+						is >> thread;
+						kill_thread(thread);
+
+						return 0;
+					}
+
+				case FIRST:
+					{
+						os << first();
+						return 0;
+					}
+
+				case NEXT:
+					{
+						Thread_capability curr_thread;
+						is >> curr_thread;
+						os << next(curr_thread);
+						return 0;
+					}
+
+				case SET_PAGER:
+					{
+						Thread_capability thread;
+						Pager_capability  pager;
+
+						is >> thread >> pager;
+						return set_pager(thread, pager);
+					}
+
+				case START:
+					{
+						Thread_capability thread;
+						addr_t ip = 0, sp = 0;
+
+						is >> thread >> ip >> sp;
+						return start(thread, ip, sp);
+					}
+
+				case CANCEL_BLOCKING:
+					{
+						Thread_capability thread;
+						is >> thread;
+						cancel_blocking(thread);
+						return 0;
+					}
+
+				case NAME:
+					{
+						Thread_capability thread;
+						is >> thread;
+						char name_buf[THREAD_NAME_LEN];
+						int res = name(thread, name_buf, sizeof(name_buf));
+						os << Buffer(name_buf);
+						return res;
+					}
+
+				case STATE:
+					{
+						Thread_capability thread;
+						Thread_state thread_state;
+						is >> thread;
+						int res = state(thread, &thread_state);
+						os << thread_state;
+						return res;
+					}
+
+				case MIGRATE:
+					{
+						Thread_capability thread;
+						unsigned cpu;
+						is >> thread >> cpu;
+						int res = migrate(thread, cpu);
+						return res;
+					}
+
+				default:
+					PWRN("unknown opcode %d", op);
+					return -1;
+				}
+			}
+	};
+}
+
+#endif /* _INCLUDE__CPU_SESSION__SERVER_H_ */
Index: base-foc/src/core/platform_thread.cc
===================================================================
--- base-foc/src/core/platform_thread.cc	(revision 143)
+++ base-foc/src/core/platform_thread.cc	(working copy)
@@ -127,6 +127,12 @@
 }
 
 
+void Platform_thread::migrate(unsigned cpu)
+{
+	/* Please implement me ! */
+}
+
+
 void Platform_thread::cancel_blocking()
 {
 	l4_irq_trigger(_irq_cap);
Index: base-foc/src/core/cpu_session_component.cc
===================================================================
--- base-foc/src/core/cpu_session_component.cc	(revision 0)
+++ base-foc/src/core/cpu_session_component.cc	(revision 0)
@@ -0,0 +1,184 @@
+/**
+ * \brief  Core implementation of the CPU session/thread interfaces
+ * \author Christian Helmuth
+ * \date   2006-07-17
+ *
+ * FIXME arg_string and quota missing
+ */
+
+/*
+ * Copyright (C) 2006-2011 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/printf.h>
+#include <util/arg_string.h>
+
+/* Core includes */
+#include <cpu_session_component.h>
+
+using namespace Genode;
+
+
+Thread_capability Cpu_session_component::create_thread(const char *name)
+{
+	Lock::Guard thread_list_lock_guard(_thread_list_lock);
+	Lock::Guard slab_lock_guard(_slab_lock);
+
+	Cpu_thread *thread = 0;
+	try {
+		thread = new(&_slab) Cpu_thread(name, _priority);
+	} catch (Allocator::Out_of_memory) {
+		throw Thread_creation_failed();
+	}
+
+	_thread_list.insert(thread);
+	return Thread_capability(_thread_ep->manage(thread));
+}
+
+
+void Cpu_session_component::_unsynchronized_kill_thread(Cpu_thread *thread)
+{
+	Lock::Guard lock_guard(_slab_lock);
+
+	_thread_ep->dissolve(thread);
+	_thread_list.remove(thread);
+
+	destroy(&_slab, thread);
+}
+
+
+void Cpu_session_component::kill_thread(Thread_capability thread_cap)
+{
+	Lock::Guard lock_guard(_thread_list_lock);
+
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return;
+
+	_unsynchronized_kill_thread(thread);
+}
+
+
+Thread_capability Cpu_session_component::first()
+{
+	Lock::Guard lock_guard(_thread_list_lock);
+
+	return _thread_list.first() ? Thread_capability(_thread_list.first()->cap())
+	                            : Thread_capability();
+}
+
+
+Thread_capability Cpu_session_component::next(Thread_capability thread_cap)
+{
+	Lock::Guard lock_guard(_thread_list_lock);
+
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+
+	if (!thread || !thread->next())
+		return Thread_capability();
+
+	return Thread_capability(thread->next()->cap());
+}
+
+
+int Cpu_session_component::set_pager(Thread_capability thread_cap,
+                                     Pager_capability  pager_cap)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return -1;
+
+	Pager_object *p = dynamic_cast<Pager_object *>(_pager_ep->obj_by_cap(pager_cap));
+	if (!p) return -2;
+
+	thread->platform_thread()->pager(p);
+	return 0;
+}
+
+
+int Cpu_session_component::start(Thread_capability thread_cap,
+                                 addr_t ip, addr_t sp)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return -1;
+
+	thread->platform_thread()->start((void *)ip, (void *)sp);
+	return 0;
+}
+
+
+void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+
+	if (thread)
+		thread->platform_thread()->cancel_blocking();
+}
+
+
+int Cpu_session_component::name(Thread_capability thread_cap,
+                                char *name_dst, size_t name_len)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return -1;
+
+	strncpy(name_dst, thread->platform_thread()->name(), name_len);
+	return 0;
+}
+
+
+int Cpu_session_component::state(Thread_capability thread_cap,
+                                 Thread_state *state_dst)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return -1;
+
+	thread->platform_thread()->state(state_dst);
+	return 0;
+}
+
+
+int Cpu_session_component::migrate(Thread_capability thread_cap,
+                                   unsigned          cpu)
+{
+	Cpu_thread *thread = _lookup_thread(thread_cap);
+	if (!thread) return -1;
+
+	thread->platform_thread()->migrate(cpu);
+	return 0;
+}
+
+
+Cpu_session_component::Cpu_session_component(Server_entrypoint *thread_ep,
+                                             Pager_entrypoint *pager_ep,
+                                             Allocator *md_alloc,
+                                             const char *args)
+: _thread_ep(thread_ep), _pager_ep(pager_ep),
+  _md_alloc(md_alloc, Arg_string::find_arg(args, "ram_quota").long_value(0)),
+  _slab(&_md_alloc), _priority(0)
+{
+	Arg a = Arg_string::find_arg(args, "priority");
+	if (a.valid()) {
+		_priority = a.ulong_value(0);
+
+		/* clamp priority value to valid range */
+		_priority = min((unsigned)PRIORITY_LIMIT - 1, _priority);
+	}
+}
+
+
+Cpu_session_component::~Cpu_session_component()
+{
+	Lock::Guard lock_guard(_thread_list_lock);
+
+	/*
+	 * We have to keep the '_thread_list_lock' during the whole destructor to
+	 * prevent races with incoming calls of the 'create_thread' function,
+	 * adding new threads while we are destroying them.
+	 */
+
+	for (Cpu_thread *thread; (thread = _thread_list.first()); )
+		_unsynchronized_kill_thread(thread);
+}
Index: base-foc/src/core/include/platform_thread.h
===================================================================
--- base-foc/src/core/include/platform_thread.h	(revision 143)
+++ base-foc/src/core/include/platform_thread.h	(working copy)
@@ -110,7 +110,9 @@
 			 */
 			int state(Genode::Thread_state *state_dst);
 
+			void migrate(unsigned cpu);
 
+
 			/************************
 			 ** Accessor functions **
 			 ************************/
Index: base-foc/src/core/include/cpu_session_component.h
===================================================================
--- base-foc/src/core/include/cpu_session_component.h	(revision 0)
+++ base-foc/src/core/include/cpu_session_component.h	(revision 0)
@@ -0,0 +1,135 @@
+/*
+ * \brief  Core-specific instance of the CPU session/thread interfaces
+ * \author Christian Helmuth
+ * \date   2006-07-17
+ */
+
+/*
+ * Copyright (C) 2006-2011 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 _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
+#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
+
+/* Genode includes */
+#include <util/list.h>
+#include <base/allocator_guard.h>
+#include <base/tslab.h>
+#include <base/lock.h>
+#include <base/pager.h>
+#include <cpu_session/server.h>
+
+/* core includes */
+#include <platform_thread.h>
+
+namespace Genode {
+
+	/*
+	 * We make Cpu_thread a server object only to be able
+	 * to use the 'Capability' -> 'Server_object' lookup
+	 * functionality of an entry point. It does not provide
+	 * a RPC interface.
+	 */
+	class Cpu_thread : public Server_object,
+	                   public List<Cpu_thread>::Element
+	{
+		private:
+
+			Platform_thread _platform_thread;
+
+			bool            _bound;            /* pd binding flag */
+
+		public:
+
+			Cpu_thread(const char *name, unsigned priority)
+			: _platform_thread(name, priority), _bound(false) { }
+
+
+			/************************
+			 ** Accessor functions **
+			 ************************/
+
+			inline Platform_thread * platform_thread() { return &_platform_thread; }
+			inline bool bound() const                  { return _bound; }
+			inline void bound(bool b)                  { _bound = b; }
+
+
+			/*****************************
+			 ** Server object interface **
+			 ****************************/
+
+			int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) { return 0; }
+	};
+
+
+	class Cpu_session_component : public Cpu_session_server
+	{
+		private:
+
+			Server_entrypoint      *_thread_ep;
+			Pager_entrypoint       *_pager_ep;
+			Allocator_guard         _md_alloc;          /* guarded meta-data allocator */
+			Tslab<Cpu_thread, 1024> _slab;              /* meta-data allocator */
+			Lock                    _slab_lock;         /* protect slab access */
+			List<Cpu_thread>        _thread_list;
+			Lock                    _thread_list_lock;  /* protect thread list */
+			unsigned                _priority;          /* priority of threads
+			                                               created with this
+			                                               session */
+
+			/**
+			 * Lookup thread in CPU session by its capability
+			 *
+			 * \retval NULL  thread capability is invalid or
+			 *               does not belong to the CPU session
+			 */
+			Cpu_thread *_lookup_thread(Thread_capability thread) {
+				return dynamic_cast<Cpu_thread *>
+				       (_thread_ep->obj_by_cap(thread)); }
+
+			/**
+			 * Raw thread-killing functionality
+			 *
+			 * This function is called from the 'kill_thread' function and
+			 * the destructor. Each these functions grab the list lock
+			 * by themselves and call this function to perform the actual
+			 * killing.
+			 */
+			void _unsynchronized_kill_thread(Cpu_thread *thread);
+
+		public:
+
+			/**
+			 * Constructor
+			 */
+			Cpu_session_component(Server_entrypoint *thread_ep,
+			                      Pager_entrypoint  *pager_ep,
+			                      Allocator *md_alloc, const char *args);
+
+			/**
+			 * Destructor
+			 */
+			~Cpu_session_component();
+
+
+			/***************************
+			 ** CPU session interface **
+			 ***************************/
+
+			Thread_capability create_thread(const char *);
+			void kill_thread(Thread_capability);
+			Thread_capability first();
+			Thread_capability next(Thread_capability);
+			int set_pager(Thread_capability, Pager_capability);
+			int start(Thread_capability, addr_t, addr_t);
+			void cancel_blocking(Thread_capability);
+			int name(Thread_capability, char *, size_t);
+			int state(Thread_capability, Thread_state *);
+			int migrate(Thread_capability, unsigned);
+	};
+}
+
+#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
Index: base-foc/src/core/target.inc
===================================================================
--- base-foc/src/core/target.inc	(revision 143)
+++ base-foc/src/core/target.inc	(working copy)
@@ -38,7 +38,6 @@
 vpath multiboot_info.cc           $(GEN_CORE_DIR)
 vpath ram_session_component.cc    $(GEN_CORE_DIR)
 vpath rom_session_component.cc    $(GEN_CORE_DIR)
-vpath cpu_session_component.cc    $(GEN_CORE_DIR)
 vpath pd_session_component.cc     $(GEN_CORE_DIR)
 vpath rm_session_component.cc     $(GEN_CORE_DIR)
 vpath io_mem_session_component.cc $(GEN_CORE_DIR)
------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
_______________________________________________
Genode-main mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/genode-main

Reply via email to