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_ */