1 /*
2 * \brief Thread interface
3 * \author Norman Feske
4 * \date 2006-04-28
5 */
6
7 /*
8 * Copyright (C) 2006-2016 Genode Labs GmbH
9 *
10 * This file is part of the Genode OS framework, which is distributed
11 * under the terms of the GNU General Public License version 2.
12 */
13
14 #ifndef _INCLUDE__BASE__THREAD_H_
15 #define _INCLUDE__BASE__THREAD_H_
16
17 /* Genode includes */
18 #include <base/exception.h>
19 #include <base/lock.h>
20 #include <base/native_types.h>
21 #include <base/trace/logger.h>
22 #include <cpu/consts.h>
23 #include <util/string.h>
24 #include <util/bit_allocator.h>
25 #include <ram_session/ram_session.h> /* for `Ram_dataspace_capability` type */
26 #include <cpu_session/cpu_session.h> /* for `Thread_capability` type */
27 #include <cpu_session/capability.h> /* for `Cpu_session_capability` type */
28
29 namespace Genode {
30
31 struct Native_utcb;
32 class Rm_session;
33 class Thread_base;
34 class Stack;
35 template <unsigned> class Thread;
36 }
37
38
39 /**
40 * Concurrent control flow
41 *
42 * A `Thread_base` object corresponds to a physical thread. The execution
43 * starts at the `entry()` method as soon as `start()` is called.
44 */
45 class Genode::Thread_base
46 {
47 public:
48
49 class Out_of_stack_space : public Exception { };
50 class Stack_too_large : public Exception { };
51 class Stack_alloc_failed : public Exception { };
52
53 private:
54
55 /**
56 * Allocate and locally attach a new stack
57 *
58 * \param stack_size size of this threads stack
59 * \param main_thread wether this is the main thread
60 */
61 Stack *_alloc_stack(size_t stack_size, char const *name, bool main_thread);
62
63 /**
64 * Detach and release stack of the thread
65 */
66 void _free_stack(Stack *stack);
67
68 /**
69 * Platform-specific thread-startup code
70 *
71 * On some platforms, each new thread has to perform a startup
72 * protocol, e.g., waiting for a message from the kernel. This hook
73 * method allows for the implementation of such protocols.
74 */
75 void _thread_bootstrap();
76
77 /**
78 * Helper for thread startup
79 */
80 static void _thread_start();
81
82 /**
83 * Hook for platform-specific destructor supplements
84 */
85 void _deinit_platform_thread();
86
87 protected:
88
89 /**
90 * Capability for this thread (set by _start())
91 *
92 * Used if thread creation involves core`s CPU service.
93 */
94 Genode::Thread_capability _thread_cap;
95
96 /**
97 * Capability to pager paging this thread (created by _start())
98 */
99 Genode::Pager_capability _pager_cap;
100
101 /**
102 * Pointer to cpu session used for this thread
103 */
104 Genode::Cpu_session *_cpu_session;
105
106 /**
107 * Base pointer to Trace::Control area used by this thread
108 */
109 Trace::Control *_trace_control;
110
111 /**
112 * Pointer to primary stack
113 */
114 Stack *_stack;
115
116 /**
117 * Physical thread ID
118 */
119 Native_thread _tid;
120
121 /**
122 * Lock used for synchronizing the finalization of the thread
123 */
124 Genode::Lock _join_lock;
125
126 /**
127 * Thread type
128 *
129 * Some threads need special treatment at construction. This enum
130 * is solely used to distinguish them at construction.
131 */
132 enum Type { NORMAL, MAIN, REINITIALIZED_MAIN };
133
134 private:
135
136 Trace::Logger _trace_logger;
137
138 /**
139 * Return `Trace::Logger` instance of calling thread
140 *
141 * This method is used by the tracing framework internally.
142 */
143 static Trace::Logger *_logger();
144
145 /**
146 * Hook for platform-specific constructor supplements
147 *
148 * \param weight weighting regarding the CPU session quota
149 * \param type enables selection of special initialization
150 */
151 void _init_platform_thread(size_t weight, Type type);
152
153 public:
154
155 /**
156 * Constructor
157 *
158 * \noapi
159 *
160 * FIXME: With type = Forked_main_thread the stack allocation
161 * gets skipped but we should at least set Stack::ds_cap in a
162 * way that it references the dataspace of the already attached
163 * stack.
164 */
165 Thread_base(size_t weight, const char *name, size_t stack_size,
166 Type type);
167
168 /**
169 * Constructor
170 *
171 * \param weight weighting regarding the CPU session quota
172 * \param name thread name (for debugging)
173 * \param stack_size stack size
174 *
175 * \throw Stack_too_large
176 * \throw Stack_alloc_failed
177 * \throw Out_of_stack_space
178 *
179 * The stack for the new thread will be allocated from the RAM session
180 * of the component environment. A small portion of the stack size is
181 * internally used by the framework for storing thread-specific
182 * information such as the thread`s name.
183 */
184 Thread_base(size_t weight, const char *name, size_t stack_size)
185 : Thread_base(weight, name, stack_size, NORMAL) { }
186
187 /**
188 * Constructor
189 *
190 * Variant of the constructor that allows the use of a different
191 * CPU session.
192 *
193 * \noapi Using multiple CPU sessions within a single component is
194 * an experimental feature.
195 *
196 * \param weight weighting regarding the CPU session quota
197 * \param name thread name (for debugging)
198 * \param stack_size stack size
199 * \param type enables selection of special construction
200 * \param cpu_session capability to cpu session used for construction
201 *
202 * \throw Stack_too_large
203 * \throw Stack_alloc_failed
204 * \throw Out_of_stack_space
205 */
206 Thread_base(size_t weight, const char *name, size_t stack_size,
207 Type type, Cpu_session *);
208
209 /**
210 * Destructor
211 */
212 virtual ~Thread_base();
213
214 /**
215 * Entry method of the thread
216 */
217 virtual void entry() = 0;
218
219 /**
220 * Start execution of the thread
221 *
222 * This method is virtual to enable the customization of threads
223 * used as server activation.
224 */
225 virtual void start();
226
227 /**
228 * Request name of thread
229 */
230 void name(char *dst, size_t dst_len);
231
232 /**
233 * Add an additional stack to the thread
234 *
235 * \throw Stack_too_large
236 * \throw Stack_alloc_failed
237 * \throw Out_of_stack_space
238 *
239 * The stack for the new thread will be allocated from the RAM
240 * session of the component environment. A small portion of the
241 * stack size is internally used by the framework for storing
242 * thread-specific information such as the thread`s name.
243 *
244 * \return pointer to the new stack`s top
245 */
246 void* alloc_secondary_stack(char const *name, size_t stack_size);
247
248 /**
249 * Remove a secondary stack from the thread
250 */
251 void free_secondary_stack(void* stack_addr);
252
253 /**
254 * Request capability of thread
255 */
256 Genode::Thread_capability cap() const { return _thread_cap; }
257
258 /**
259 * Cancel currently blocking operation
260 */
261 void cancel_blocking();
262
263 /**
264 * Return thread ID
265 *
266 * \noapi Only to be called from platform-specific code
267 */
268 Native_thread & tid() { return _tid; }
269
270 /**
271 * Return top of stack
272 *
273 * \return pointer just after first stack element
274 */
275 void *stack_top() const;
276
277 /**
278 * Return base of stack
279 *
280 * \return pointer to last stack element
281 */
282 void *stack_base() const;
283
284 /**
285 * Return virtual size reserved for each stack within the stack area
286 */
287 static size_t stack_virtual_size();
288
289 /**
290 * Return the local base address of the stack area
291 */
292 static addr_t stack_area_virtual_base();
293
294 /**
295 * Return total size of the stack area
296 */
297 static size_t stack_area_virtual_size();
298
299 /**
300 * Return `Thread_base` object corresponding to the calling thread
301 *
302 * \return pointer to caller`s `Thread_base` object
303 */
304 static Thread_base *myself();
305
306 /**
307 * Ensure that the stack has a given size at the minimum
308 *
309 * \param size minimum stack size
310 *
311 * \throw Stack_too_large
312 * \throw Stack_alloc_failed
313 */
314 void stack_size(size_t const size);
315
316 /**
317 * Return user-level thread control block
318 *
319 * Note that it is safe to call this method on the result of the
320 * `myself` class function. It handles the special case of `myself`
321 * being 0 when called by the main thread during the component
322 * initialization phase.
323 */
324 Native_utcb *utcb();
325
326 /**
327 * Block until the thread leaves the `entry` method
328 *
329 * Join must not be called more than once. Subsequent calls have
330 * undefined behaviour.
331 */
332 void join();
333
334 /**
335 * Log null-terminated string as trace event
336 */
337 static void trace(char const *cstring)
338 {
339 _logger()->log(cstring, strlen(cstring));
340 }
341
342 /**
343 * Log binary data as trace event
344 */
345 static void trace(char const *data, size_t len)
346 {
347 _logger()->log(data, len);
348 }
349
350 /**
351 * Log trace event as defined in base/trace.h
352 */
353 template <typename EVENT>
354 static void trace(EVENT const *event) { _logger()->log(event); }
355 };
356
357
358 template <unsigned STACK_SIZE>
359 class Genode::Thread : public Thread_base
360 {
361 public:
362
363 /**
364 * Constructor
365 *
366 * \param weight weighting regarding the CPU session quota
367 * \param name thread name (for debugging)
368 * \param type enables selection of special construction
369 */
370 explicit Thread(size_t weight, const char *name)
371 : Thread_base(weight, name, STACK_SIZE, Type::NORMAL) { }
372
373 /**
374 * Constructor
375 *
376 * \param weight weighting regarding the CPU session quota
377 * \param name thread name (for debugging)
378 * \param type enables selection of special construction
379 *
380 * \noapi
381 */
382 explicit Thread(size_t weight, const char *name, Type type)
383 : Thread_base(weight, name, STACK_SIZE, type) { }
384
385 /**
386 * Constructor
387 *
388 * \param weight weighting regarding the CPU session quota
389 * \param name thread name (for debugging)
390 * \param cpu_session thread created via specific cpu session
391 *
392 * \noapi
393 */
394 explicit Thread(size_t weight, const char *name,
395 Cpu_session * cpu_session)
396 : Thread_base(weight, name, STACK_SIZE, Type::NORMAL, cpu_session) { }
397
398 /**
399 * Shortcut for `Thread(DEFAULT_WEIGHT, name, type)`
400 *
401 * \noapi
402 */
403 explicit Thread(const char *name, Type type = NORMAL)
404 : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE, type) { }
405
406 /**
407 * Shortcut for `Thread(DEFAULT_WEIGHT, name, cpu_session)`
408 *
409 * \noapi
410 */
411 explicit Thread(const char *name, Cpu_session * cpu_session)
412 : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE,
413 Type::NORMAL, cpu_session)
414 { }
415 };
416
417 #endif /* _INCLUDE__BASE__THREAD_H_ */