// vi:ft=cpp /** * \file * \brief Common thread related definitions. */ /* * (c) 2008-2009 Adam Lackorzynski , * Alexander Warg * economic rights: Technische Universität Dresden (Germany) * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. * Please see the COPYING-GPL-2 file for details. * * As a special exception, you may use this file as part of a free software * library without restriction. Specifically, if other files instantiate * templates or use macros or inline functions from this file, or you compile * this file and link it with other files to produce an executable, this * file does not by itself cause the resulting executable to be covered by * the GNU General Public License. This exception does not however * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. */ #pragma once #include #include namespace L4 { /** * \ingroup l4_thread_api * \brief L4 kernel thread. * * \#include */ class Thread : public Kobject_t { L4_KOBJECT(Thread) public: /** * \copydoc l4_thread_ex_regs() * \note the \a thread argument is the implicit \a this pointer. */ l4_msgtag_t ex_regs(l4_addr_t ip, l4_addr_t sp, l4_umword_t flags, l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_ex_regs_u(cap(), ip, sp, flags, utcb); } /** * \copydoc l4_thread_ex_regs_ret() * \note the \a thread argument is the implicit \a this pointer. */ l4_msgtag_t ex_regs(l4_addr_t *ip, l4_addr_t *sp, l4_umword_t *flags, l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_ex_regs_ret_u(cap(), ip, sp, flags, utcb); } /** * \brief Thread attributes used for control_commit(). * * This class is responsible for initalizing various attributes of a * thread in a UTCB for the control_commit() method. * * \see \ref l4_thread_control_api for some more details. */ class Attr { private: friend class L4::Thread; l4_utcb_t *_u; public: /** * \brief Create a thread-attribute object with the given UTCB. * \param utcb the UTCB to use for the later L4::Thread::control_commit() * function. Usually this is the UTCB of the calling thread. */ explicit Attr(l4_utcb_t *utcb = l4_utcb()) throw() : _u(utcb) { l4_thread_control_start_u(utcb); } /** * \brief Set the pager capability selector. * \param pager the capability selector that shall be used for page-fault * messages. This capability selector must be valid within * the task the thread is bound to. */ void pager(Cap const &pager) throw() { l4_thread_control_pager_u(pager.cap(), _u); } /** * \brief Get the capability selector used for page-fault messages. * \return the capability selector used to send page-fault messages. The * selector is valid in the task the thread is bound to. */ Cap pager() throw() { return Cap(l4_utcb_mr_u(_u)->mr[1]); } /** * \brief Set the exception-handler capability selector. * \param pager the capability selector that shall be used for exception * messages. This capability selector must be * valid within the task the thread is bound to. */ void exc_handler(Cap const &exc_handler) throw() { l4_thread_control_exc_handler_u(exc_handler.cap(), _u); } /** * \brief Get the capability selector used for exception messages. * \return the capability selector used to send exception messages. The * selector is valid in the task the thread is bound to. */ Cap exc_handler() throw() { return Cap(l4_utcb_mr_u(_u)->mr[2]); } /** * \brief Set the scheduler capability selector. * \param pager the capability selector that shall be used for scheduling * messages. This capability selector must be * valid within the task the thread is bound to. */ void scheduler(Cap const &scheduler) throw() { l4_thread_control_scheduler_u(scheduler.cap(), _u); } /** * \brief Get the capability selector used for scheduling messages. * \return the capability selector used to send scheduling messages. The * selector is valid in the task the thread is bound to. */ Cap scheduler() throw() { return Cap(l4_utcb_mr_u(_u)->mr[2]); } /** * \brief Bind the thread to a task. * \param thread_utcb the UTCB address of the thread within the task * specified by \a task. * \param task the capability selector for the task the thread * shall be bound to. * * Binding a thread to a task means that the thread shall afterwards * execute in the given task. To actually start execution you need * to use L4::Thread::ex_regs(). */ void bind(l4_utcb_t *thread_utcb, Cap const &task) throw() { l4_thread_control_bind_u(thread_utcb, task.cap(), _u); } /** * \brief Set the thread to alien mode. */ void alien(int on) throw() { l4_thread_control_alien_u(_u, on); } /** * \brief Allow host system calls on Fiasco-UX. * \pre Running on Fiasco-UX. */ void ux_host_syscall(int on) throw() { l4_thread_control_ux_host_syscall_u(_u, on); } }; /** * \brief Commit the given thread-attributes object. * \param attr the attribute object to commit to the thread. */ l4_msgtag_t control(Attr const &attr) throw() { return l4_thread_control_commit_u(cap(), attr._u); } /** * \brief Switch execution to this thread. * \param utcb the UTCB of the current thread. * * \note The current time slice is inherited to this thread. */ l4_msgtag_t switch_to(l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_switch_u(cap(), utcb); } /** * \brief Get consumed timed of thread in ns. * \param utcb the UTCB of the current thread. * * The consumed time is return as l4_kernel_clock_t at UTCB message * register 0. */ l4_msgtag_t stats_time(l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_stats_time_u(cap(), utcb); } /** * \brief vCPU resume, start. * * \see l4_thread_vcpu_resume_start */ l4_msgtag_t vcpu_resume_start(l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_vcpu_resume_start_u(utcb); } /** * \brief vCPU resume, commit. * * \see l4_thread_vcpu_resume_commit */ l4_msgtag_t vcpu_resume_commit(l4_msgtag_t tag, l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_vcpu_resume_commit_u(cap(), tag, utcb); } /** * \copydoc l4_thread_vcpu_control() */ l4_msgtag_t vcpu_control(l4_addr_t vcpu_state, l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_vcpu_control_u(cap(), vcpu_state, utcb); } /** * \copydoc l4_thread_vcpu_control_exit() */ l4_msgtag_t vcpu_control_ext(l4_addr_t ext_vcpu_state, l4_utcb_t *utcb = l4_utcb()) throw() { return l4_thread_vcpu_control_ext_u(cap(), ext_vcpu_state, utcb); } /** * \brief Register an IRQ that will trigger upon deletion events. * * \see l4_thread_register_del_irq */ l4_msgtag_t register_del_irq(Cap irq, l4_utcb_t *u = l4_utcb()) throw() { return l4_thread_register_del_irq_u(cap(), irq.cap(), u); } /** * \brief Wrapper class for modifying senders. * * Use the add() function to add modification rules, and use * modify_senders() to commit. Do not use the UTCB inbetween as it is * used by add() and modify_senders(). */ class Modify_senders { private: friend class Thread; l4_utcb_t *utcb; unsigned cnt; public: explicit Modify_senders(l4_utcb_t *u = l4_utcb()) throw() : utcb(u), cnt(1) { l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_MODIFY_SENDER; } /** * \brief Add a rule. * * \param match_mask Bitmask of bits to match the label. * \param match Bitmask that must be equal to the label after applying * match_mask. * \param del_bits Bits to be deleted from the label. * \param add_bits Bits to be added to the label. * * \return 0 on sucess, <0 on error * * Only the first match is applied. * * \see l4_thread_modify_sender_add() */ int add(l4_umword_t match_mask, l4_umword_t match, l4_umword_t del_bits, l4_umword_t add_bits) throw() { l4_msg_regs_t *m = l4_utcb_mr_u(utcb); if (cnt >= L4_UTCB_GENERIC_DATA_SIZE - 4) return -L4_ENOMEM; m->mr[cnt++] = match_mask; m->mr[cnt++] = match; m->mr[cnt++] = del_bits; m->mr[cnt++] = add_bits; return 0; } }; /** * \brief Apply sender modifiction rules. * * \param todo Prepared sender modification rules. * * \return System call return tag. */ l4_msgtag_t modify_senders(Modify_senders const &todo) throw() { return l4_ipc_call(cap(), todo.utcb, l4_msgtag(L4_PROTO_THREAD, todo.cnt, 0, 0), L4_IPC_NEVER); } }; }