L4Re - L4 Runtime Environment
thread
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /**
3  * \file
4  * Common thread related definitions.
5  */
6 /*
7  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  * Alexander Warg <warg@os.inf.tu-dresden.de>
9  * economic rights: Technische Universität Dresden (Germany)
10  *
11  * This file is part of TUD:OS and distributed under the terms of the
12  * GNU General Public License 2.
13  * Please see the COPYING-GPL-2 file for details.
14  *
15  * As a special exception, you may use this file as part of a free software
16  * library without restriction. Specifically, if other files instantiate
17  * templates or use macros or inline functions from this file, or you compile
18  * this file and link it with other files to produce an executable, this
19  * file does not by itself cause the resulting executable to be covered by
20  * the GNU General Public License. This exception does not however
21  * invalidate any other reasons why the executable file might be covered by
22  * the GNU General Public License.
23  */
24 
25 #pragma once
26 
27 #include <l4/sys/capability>
28 #include <l4/sys/thread.h>
29 
30 namespace L4 {
31 
32 /**
33  * C++ L4 kernel thread interface.
34  *
35  * The Thread class defines a thread of execution in the L4 context.
36  * Usually user-level and kernel threads are mapped 1:1 to each other.
37  * Thread kernel objects are created using a factory, see the L4::Factory API
38  * (L4::Factory::create()).
39  *
40  * Amongst other things an L4::Thread encapsulates:
41  * - CPU state
42  * - General-purpose registers
43  * - Program counter
44  * - Stack pointer
45  * - FPU state
46  * - Scheduling parameters, see the L4::Scheduler API
47  * - Execution state
48  * - Blocked, Runnable, Running
49  *
50  * Thread objects provide an API for
51  * - Thread configuration and manipulation
52  * - Thread switching.
53  *
54  * \includefile{l4/sys/thread}
55  *
56  * For the C interface see the \ref l4_thread_api API.
57  */
58 class Thread :
59  public Kobject_t<Thread, Kobject, L4_PROTO_THREAD,
60  Type_info::Demand_t<1> >
61 {
62 public:
63  /**
64  * Exchange basic thread registers.
65  *
66  * \param ip New instruction pointer, use ~0UL to leave the
67  * instruction pointer unchanged.
68  * \param sp New stack pointer, use ~0UL to leave the stack
69  * pointer unchanged.
70  * \param flags Ex-regs flags, see #L4_thread_ex_regs_flags.
71  * \param utcb UTCB to use for this operation.
72  *
73  * \return System call return tag
74  *
75  * This method allows to manipulate a thread. The basic functionality is to
76  * set the instruction pointer and the stack pointer of a thread.
77  * Additionally, this method allows also to cancel ongoing IPC operations and
78  * to force the thread to raise an artificial exception (see `flags`).
79  *
80  * The thread is started using L4::Scheduler::run_thread(). However, if at
81  * the time L4::Scheduler::run_thread() is called, the instruction pointer of
82  * the thread is invalid, a later call to ex_regs() with a valid instruction
83  * pointer might start the thread.
84  */
85  l4_msgtag_t ex_regs(l4_addr_t ip, l4_addr_t sp,
86  l4_umword_t flags,
87  l4_utcb_t *utcb = l4_utcb()) throw()
88  { return l4_thread_ex_regs_u(cap(), ip, sp, flags, utcb); }
89 
90  /**
91  * Exchange basic thread registers and return previous values.
92  *
93  * \param[in,out] ip New instruction pointer, use ~0UL to leave the
94  * instruction pointer unchanged, return previous
95  * instruction pointer.
96  * \param[in,out] sp New stack pointer, use ~0UL to leave the stack
97  * pointer unchanged, returns previous stack pointer.
98  * \param[in,out] flags Ex-regs flags, see #L4_thread_ex_regs_flags, return
99  * previous CPU flags of the thread.
100  * \param utcb UTCB to use for this operation.
101  *
102  * \return System call return tag. [out] parameters are only valid if the
103  * function returns successfully. Use l4_error() to check.
104  *
105  * This method allows to manipulate and start a thread. The basic
106  * functionality is to set the instruction pointer and the stack pointer of a
107  * thread. Additionally, this method allows also to cancel ongoing IPC
108  * operations and to force the thread to raise an artificial exception (see
109  * `flags`).
110  */
111  l4_msgtag_t ex_regs(l4_addr_t *ip, l4_addr_t *sp,
112  l4_umword_t *flags,
113  l4_utcb_t *utcb = l4_utcb()) throw()
114  { return l4_thread_ex_regs_ret_u(cap(), ip, sp, flags, utcb); }
115 
116 
117  /**
118  * Thread attributes used for control_commit().
119  *
120  * This class is responsible for initializing various attributes of a
121  * thread in a UTCB for the control_commit() method.
122  *
123  * \see \ref l4_thread_control_api for some more details.
124  */
125  class Attr
126  {
127  private:
128  friend class L4::Thread;
129  l4_utcb_t *_u;
130 
131  public:
132  /**
133  * Create a thread-attribute object with the given UTCB.
134  *
135  * \param utcb The UTCB to use for the later L4::Thread::control_commit()
136  * function. Usually this is the UTCB of the calling thread.
137  */
138  explicit Attr(l4_utcb_t *utcb = l4_utcb()) throw() : _u(utcb)
139  { l4_thread_control_start_u(utcb); }
140 
141  /**
142  * Set the pager capability selector.
143  *
144  * \param pager The capability selector that shall be used for page-fault
145  * messages. This capability selector must be valid within
146  * the task the thread is bound to.
147  */
148  void pager(Cap<void> const &pager) throw()
149  { l4_thread_control_pager_u(pager.cap(), _u); }
150 
151  /**
152  * Get the capability selector used for page-fault messages.
153  *
154  * \return The capability selector used to send page-fault messages. The
155  * selector is valid in the task the thread is bound to.
156  */
157  Cap<void> pager() throw()
158  { return Cap<void>(l4_utcb_mr_u(_u)->mr[1]); }
159 
160  /**
161  * Set the exception-handler capability selector.
162  *
163  * \param exc_handler The capability selector that shall be used for
164  * exception messages. This capability selector must
165  * be valid within the task the thread is bound to.
166  */
167  void exc_handler(Cap<void> const &exc_handler) throw()
168  { l4_thread_control_exc_handler_u(exc_handler.cap(), _u); }
169 
170  /**
171  * Get the capability selector used for exception messages.
172  *
173  * \return The capability selector used to send exception messages. The
174  * selector is valid in the task the thread is bound to.
175  */
176  Cap<void> exc_handler() throw()
177  { return Cap<void>(l4_utcb_mr_u(_u)->mr[2]); }
178 
179  /**
180  * Bind the thread to a task.
181  *
182  * \param thread_utcb The UTCB address of the thread within the task
183  * specified by `task`.
184  * \param task The capability selector for the task the thread
185  * shall be bound to.
186  *
187  * Binding a thread to a task means that the thread shall afterwards
188  * execute in the given task. To actually start execution you need
189  * to use L4::Thread::ex_regs().
190  */
191  void bind(l4_utcb_t *thread_utcb, Cap<Task> const &task) throw()
192  { l4_thread_control_bind_u(thread_utcb, task.cap(), _u); }
193 
194  /**
195  * Set the thread to alien mode.
196  */
197  void alien(int on) throw()
198  { l4_thread_control_alien_u(_u, on); }
199 
200  /**
201  * Allow host system calls on Fiasco-UX.
202  *
203  * \pre Running on Fiasco-UX.
204  */
205  void ux_host_syscall(int on) throw()
206  { l4_thread_control_ux_host_syscall_u(_u, on); }
207 
208  };
209 
210  /**
211  * Commit the given thread-attributes object.
212  *
213  * \param attr the attribute object to commit to the thread.
214  */
215  l4_msgtag_t control(Attr const &attr) throw()
216  { return l4_thread_control_commit_u(cap(), attr._u); }
217 
218  /**
219  * Switch execution to this thread.
220  *
221  * \param utcb the UTCB of the current thread.
222  *
223  * \note The current time slice is inherited to this thread.
224  */
225  l4_msgtag_t switch_to(l4_utcb_t *utcb = l4_utcb()) throw()
226  { return l4_thread_switch_u(cap(), utcb); }
227 
228  /**
229  * Get consumed time of thread in us.
230  *
231  * \param[out] us Consumed time in µs.
232  * \param utcb UTCB of the current thread.
233  *
234  * \return Syscall return tag.
235  */
236  l4_msgtag_t stats_time(l4_kernel_clock_t *us,
237  l4_utcb_t *utcb = l4_utcb()) throw()
238  { return l4_thread_stats_time_u(cap(), us, utcb); }
239 
240  /**
241  * vCPU resume, start.
242  *
243  * \see l4_thread_vcpu_resume_start
244  */
245  l4_msgtag_t vcpu_resume_start(l4_utcb_t *utcb = l4_utcb()) throw()
246  { return l4_thread_vcpu_resume_start_u(utcb); }
247 
248  /**
249  * vCPU resume, commit.
250  *
251  * \see l4_thread_vcpu_resume_commit
252  */
253  l4_msgtag_t vcpu_resume_commit(l4_msgtag_t tag,
254  l4_utcb_t *utcb = l4_utcb()) throw()
255  { return l4_thread_vcpu_resume_commit_u(cap(), tag, utcb); }
256 
257  /**
258  * Enable or disable the vCPU feature for the thread.
259  *
260  * \param vcpu_state The virtual address where the kernel shall store the
261  * vCPU state in case of vCPU exits. The address must be
262  * a valid kernel-user-memory address (see
263  * L4::Task::add_ku_mem()).
264  * \param utcb UTCB to use for this operation.
265  *
266  * \return Syscall return tag.
267  *
268  * This function enables the vCPU feature of `this` thread if `vcpu_state`
269  * is set to a valid kernel-user-memory address, or disables the vCPU
270  * feature if `vcpu_state` is 0. (Disable: optional, currently unsupported.)
271  */
272  l4_msgtag_t vcpu_control(l4_addr_t vcpu_state, l4_utcb_t *utcb = l4_utcb())
273  throw()
274  { return l4_thread_vcpu_control_u(cap(), vcpu_state, utcb); }
275 
276  /**
277  * Enable or disable the extended vCPU feature for the thread.
278  *
279  * \param ext_vcpu_state The virtual address where the kernel shall store
280  * the vCPU state in case of vCPU exits. The address
281  * must be a valid kernel-user-memory address (see
282  * L4::Task::add_ku_mem()).
283  * \param utcb UTCB to use for this operation.
284  *
285  * \return Syscall return tag.
286  *
287  * The extended vCPU feature allows the use of hardware-virtualization
288  * features such as Intel's VT or AMD's SVM.
289  *
290  * This function enables the extended vCPU feature of `this` thread
291  * if `ext_vcpu_state` is set to a valid kernel-user-memory address, or
292  * disables the vCPU feature if `ext_vcpu_state` is 0.
293  *
294  * \note The extended vCPU mode includes the normal vCPU mode.
295  */
296  l4_msgtag_t vcpu_control_ext(l4_addr_t ext_vcpu_state,
297  l4_utcb_t *utcb = l4_utcb()) throw()
298  { return l4_thread_vcpu_control_ext_u(cap(), ext_vcpu_state, utcb); }
299 
300  /**
301  * Register an IRQ that will trigger upon deletion events.
302  *
303  * \param irq Capability selector for the IRQ object to be triggered.
304  * \utcb{u}
305  *
306  * \return System call return tag containing the return code.
307  *
308  * An example of a deletion event is the removal of an IPC gate
309  * that is bound to this thread.
310  *
311  * \see l4_thread_register_del_irq
312  */
313  l4_msgtag_t register_del_irq(Cap<Irq> irq, l4_utcb_t *u = l4_utcb()) throw()
314  { return l4_thread_register_del_irq_u(cap(), irq.cap(), u); }
315 
316  /**
317  * Wrapper class for modifying senders.
318  *
319  * Use the add() function to add modification rules, and use
320  * modify_senders() to commit. Do not use the UTCB in between as it is
321  * used by add() and modify_senders().
322  */
323  class Modify_senders
324  {
325  private:
326  friend class Thread;
327  l4_utcb_t *utcb;
328  unsigned cnt;
329 
330  public:
331  explicit Modify_senders(l4_utcb_t *u = l4_utcb()) throw()
332  : utcb(u), cnt(1)
333  {
334  l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_MODIFY_SENDER_OP;
335  }
336 
337  /**
338  * Add a rule.
339  *
340  * \param match_mask Bitmask of bits to match the label.
341  * \param match Bitmask that must be equal to the label after applying
342  * match_mask.
343  * \param del_bits Bits to be deleted from the label.
344  * \param add_bits Bits to be added to the label.
345  *
346  * \return 0 on success, <0 on error
347  *
348  * Only the first match is applied.
349  *
350  * \see l4_thread_modify_sender_add()
351  */
352  int add(l4_umword_t match_mask, l4_umword_t match,
353  l4_umword_t del_bits, l4_umword_t add_bits) throw()
354  {
355  l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
356  if (cnt >= L4_UTCB_GENERIC_DATA_SIZE - 4)
357  return -L4_ENOMEM;
358  m->mr[cnt++] = match_mask;
359  m->mr[cnt++] = match;
360  m->mr[cnt++] = del_bits;
361  m->mr[cnt++] = add_bits;
362  return 0;
363  }
364  };
365 
366  /**
367  * Apply sender modification rules.
368  *
369  * \param todo Prepared sender modification rules.
370  *
371  * \return System call return tag.
372  */
373  l4_msgtag_t modify_senders(Modify_senders const &todo) throw()
374  {
375  return l4_ipc_call(cap(), todo.utcb, l4_msgtag(L4_PROTO_THREAD, todo.cnt, 0, 0), L4_IPC_NEVER);
376  }
377 };
378 }