1
/*
2
* \brief CPU (processing time) manager session interface
3
* \author Christian Helmuth
4
* \date 2006-06-27
5
*/
6
7
/*
8
* Copyright (C) 2006-2013 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__CPU_SESSION__CPU_SESSION_H_
15
#
define _INCLUDE__CPU_SESSION__CPU_SESSION_H_
16
17
#
include <cpu_session/capability.h>
18
#
include <base/stdint.h>
19
#
include <base/exception.h>
20
#
include <base/thread_state.h>
21
#
include <base/rpc_args.h>
22
#
include <base/signal.h>
23
#
include <base/affinity.h>
24
#
include <thread/capability.h>
25
#
include <pager/capability.h>
26
#
include <session/session.h>
27
#
include <ram_session/ram_session.h>
28
29
namespace
Genode {
struct
Cpu_session;
}
30
31
32
struct
Genode::
Cpu_session :
Session
33
{
34
/*********************
35
** Exception types **
36
*********************/
37
38
class
Thread_creation_failed :
public
Exception
{
}
;
39
class
State_access_failed :
public
Exception
{
}
;
40
class
Quota_exceeded :
public
Thread_creation_failed
{
}
;
41
class
Out_of_metadata :
public
Exception
{
}
;
42
43
static
const
char *
service_name(
)
{
return
"CPU"
;
}
44
45
enum
{
THREAD_NAME_LEN =
48
}
;
46
enum
{
PRIORITY_LIMIT =
1 <<
16
}
;
47
enum
{
QUOTA_LIMIT_LOG2 =
15
}
;
48
enum
{
QUOTA_LIMIT =
1 <<
QUOTA_LIMIT_LOG2
}
;
49
enum
{
DEFAULT_PRIORITY =
0
}
;
50
enum
{
DEFAULT_WEIGHT =
10
}
;
51
52
typedef
Rpc_in_buffer<
THREAD_NAME_LEN
>
Name
;
53
54
/**
55
* Physical quota configuration
56
*/
57
struct
Quota;
58
59
virtual
~
Cpu_session(
)
{
}
60
61
/**
62
* Create a new thread
63
*
64
* \param quota CPU quota that shall be granted to the thread
65
* \param name name for the thread
66
* \param utcb Base of the UTCB that will be used by the thread
67
* \return capability representing the new thread
68
* \throw Thread_creation_failed
69
* \throw Out_of_metadata
70
* \throw Quota_exceeded
71
*/
72
virtual
Thread_capability
create_thread(
size_t
quota
,
73
Name const
&
name
,
74
addr_t
utcb
=
0
)
=
0
;
75
76
/**
77
* Get dataspace of the UTCB that is used by the specified thread
78
*/
79
virtual
Ram_dataspace_capability
utcb(
Thread_capability
thread
)
=
0
;
80
81
/**
82
* Kill an existing thread
83
*
84
* \param thread capability of the thread to kill
85
*/
86
virtual
void
kill_thread(
Thread_capability
thread
)
=
0
;
87
88
/**
89
* Set paging capabilities for thread
90
*
91
* \param thread thread to configure
92
* \param pager capability used to propagate page faults
93
*/
94
virtual
int
set_pager(
Thread_capability
thread
,
95
Pager_capability
pager
)
=
0
;
96
97
/**
98
* Modify instruction and stack pointer of thread - start the
99
* thread
100
*
101
* \param thread thread to start
102
* \param ip initial instruction pointer
103
* \param sp initial stack pointer
104
*
105
* \return 0 on success
106
*/
107
virtual
int
start(
Thread_capability
thread
,
addr_t
ip
,
addr_t
sp
)
=
0
;
108
109
/**
110
* Pause the specified thread
111
*
112
* After calling this method, the execution of the thread can be
113
* continued by calling `resume`.
114
*/
115
virtual
void
pause(
Thread_capability
thread
)
=
0
;
116
117
/**
118
* Resume the specified thread
119
*/
120
virtual
void
resume(
Thread_capability
thread
)
=
0
;
121
122
/**
123
* Cancel a currently blocking operation
124
*
125
* \param thread thread to unblock
126
*/
127
virtual
void
cancel_blocking(
Thread_capability
thread
)
=
0
;
128
129
/**
130
* Get the current state of a specific thread
131
*
132
* \param thread targeted thread
133
* \return state of the targeted thread
134
* \throw State_access_failed
135
*/
136
virtual
Thread_state
state(
Thread_capability
thread
)
=
0
;
137
138
/**
139
* Override the current state of a specific thread
140
*
141
* \param thread targeted thread
142
* \param state state that shall be applied
143
* \throw State_access_failed
144
*/
145
virtual
void
state(
Thread_capability
thread
,
146
Thread_state const
&
state
)
=
0
;
147
148
/**
149
* Register signal handler for exceptions of the specified thread
150
*
151
* If `thread` is an invalid capability, the default exception
152
* handler for the CPU session is set. This handler is used for
153
* all threads that have no explicitly installed exception handler.
154
* The new default signal handler will take effect for threads
155
* created after the call.
156
*
157
* On Linux, this exception is delivered when the process triggers
158
* a SIGCHLD. On other platforms, this exception is delivered on
159
* the occurrence of CPU exceptions such as division by zero.
160
*/
161
virtual
void
exception_handler(
Thread_capability
thread
,
162
Signal_context_capability
handler
)
=
0
;
163
164
/**
165
* Enable/disable single stepping for specified thread.
166
*
167
* Since this method is currently supported by a small number of
168
* platforms, we provide a default implementation
169
*
170
* \param thread thread to set into single step mode
171
* \param enable true = enable single-step mode; false = disable
172
*/
173
virtual
void
single_step(
Thread_capability
,
bool
)
{
}
174
175
/**
176
* Return affinity space of CPU nodes available to the CPU session
177
*
178
* The dimension of the affinity space as returned by this method
179
* represent the physical CPUs that are available.
180
*/
181
virtual
Affinity::
Space
affinity_space(
)
const
=
0
;
182
183
/**
184
* Define affinity of thread to one or multiple CPU nodes
185
*
186
* In the normal case, a thread is assigned to a single CPU.
187
* Specifying more than one CPU node is supposed to principally
188
* allow a CPU service to balance the load of threads among
189
* multiple CPUs.
190
*/
191
virtual
void
affinity(
Thread_capability
thread
,
192
Affinity::
Location
affinity
)
=
0
;
193
194
/**
195
* Translate generic priority value to kernel-specific priority levels
196
*
197
* \param pf_prio_limit maximum priority used for the kernel, must
198
* be power of 2
199
* \param prio generic priority value as used by the CPU
200
* session interface
201
* \param inverse order of platform priorities, if true
202
* `pf_prio_limit` corresponds to the highest
203
* priority, otherwise it refers to the
204
* lowest priority.
205
* \return platform-specific priority value
206
*/
207
static
unsigned
scale_priority(
unsigned
pf_prio_limit
,
unsigned
prio
,
208
bool
inverse
=
true
)
209
{
210
/*
211
* Generic priority values are (0 is highest, `PRIORITY_LIMIT`
212
* is lowest. On platforms where priority levels are defined
213
* the other way round, we have to invert the priority value.
214
*/
215
prio =
inverse ?
Cpu_session::
PRIORITY_LIMIT -
prio : prio;
216
217
/* scale value to platform priority range 0..pf_prio_limit */
218
return
(
prio*
pf_prio_limit)
/
Cpu_session::
PRIORITY_LIMIT
;
219
}
220
221
/**
222
* Request trace control dataspace
223
*
224
* The trace-control dataspace is used to propagate tracing
225
* control information from core to the threads of a CPU session.
226
*
227
* The trace-control dataspace is accounted to the CPU session.
228
*/
229
virtual
Dataspace_capability
trace_control(
)
=
0
;
230
231
/**
232
* Request index of a trace control block for given thread
233
*
234
* The trace control dataspace contains the control blocks for
235
* all threads of the CPU session. Each thread gets assigned a
236
* different index by the CPU service.
237
*/
238
virtual
unsigned
trace_control_index(
Thread_capability
thread
)
=
0
;
239
240
/**
241
* Request trace buffer for the specified thread
242
*
243
* The trace buffer is not accounted to the CPU session. It is
244
* owned by a TRACE session.
245
*/
246
virtual
Dataspace_capability
trace_buffer(
Thread_capability
thread
)
=
0
;
247
248
/**
249
* Request trace policy
250
*
251
* The trace policy buffer is not accounted to the CPU session. It
252
* is owned by a TRACE session.
253
*/
254
virtual
Dataspace_capability
trace_policy(
Thread_capability
thread
)
=
0
;
255
256
/**
257
* Define reference account for the CPU session
258
*
259
* \param cpu_session reference account
260
*
261
* \return 0 on success
262
*
263
* Each CPU session requires another CPU session as reference
264
* account to transfer quota to and from. The reference account can
265
* be defined only once.
266
*/
267
virtual
int
ref_account(
Cpu_session_capability
cpu_session
)
=
0
;
268
269
/**
270
* Transfer quota to another CPU session
271
*
272
* \param cpu_session receiver of quota donation
273
* \param amount percentage of the session quota scaled up to
274
* the `QUOTA_LIMIT` space
275
* \return 0 on success
276
*
277
* Quota can only be transfered if the specified CPU session is
278
* either the reference account for this session or vice versa.
279
*/
280
virtual
int
transfer_quota(
Cpu_session_capability
cpu_session
,
281
size_t
amount
)
=
0
;
282
283
/**
284
* Return quota configuration of the session
285
*/
286
virtual
Quota
quota(
)
=
0
;
287
288
/**
289
* Scale up `value` from its space with `limit` to the `QUOTA_LIMIT` space
290
*/
291
template
<
typename
T
=
size_t
>
292
static
size_t
quota_lim_upscale(
size_t const
value
,
size_t const
limit
)
{
293
return
(
(
T)
value <<
Cpu_session::
QUOTA_LIMIT_LOG2)
/
limit
;
}
294
295
/**
296
* Scale down `value` from the `QUOTA_LIMIT` space to a space with `limit`
297
*/
298
template
<
typename
T
=
size_t
>
299
static
size_t
quota_lim_downscale(
size_t const
value
,
size_t const
limit
)
{
300
return
(
(
T)
value *
limit)
>>
Cpu_session::
QUOTA_LIMIT_LOG2
;
}
301
302
/*********************
303
** RPC declaration **
304
*********************/
305
306
GENODE_RPC_THROW
(
Rpc_create_thread,
Thread_capability,
create_thread,
307
GENODE_TYPE_LIST
(
Thread_creation_failed,
Out_of_metadata)
,
308
size_t,
Name const
&
,
addr_t)
;
309
GENODE_RPC
(
Rpc_utcb,
Ram_dataspace_capability,
utcb,
Thread_capability)
;
310
GENODE_RPC
(
Rpc_kill_thread,
void,
kill_thread,
Thread_capability)
;
311
GENODE_RPC
(
Rpc_set_pager,
int,
set_pager,
Thread_capability,
Pager_capability)
;
312
GENODE_RPC
(
Rpc_start,
int,
start,
Thread_capability,
addr_t,
addr_t)
;
313
GENODE_RPC
(
Rpc_pause,
void,
pause,
Thread_capability)
;
314
GENODE_RPC
(
Rpc_resume,
void,
resume,
Thread_capability)
;
315
GENODE_RPC
(
Rpc_cancel_blocking,
void,
cancel_blocking,
Thread_capability)
;
316
GENODE_RPC_THROW
(
Rpc_get_state,
Thread_state,
state,
317
GENODE_TYPE_LIST
(
State_access_failed)
,
318
Thread_capability)
;
319
GENODE_RPC_THROW
(
Rpc_set_state,
void,
state,
320
GENODE_TYPE_LIST
(
State_access_failed)
,
321
Thread_capability,
Thread_state const
&
)
;
322
GENODE_RPC
(
Rpc_exception_handler,
void,
exception_handler,
323
Thread_capability,
Signal_context_capability)
;
324
GENODE_RPC
(
Rpc_single_step,
void,
single_step,
Thread_capability,
bool)
;
325
GENODE_RPC
(
Rpc_affinity_space,
Affinity::
Space,
affinity_space)
;
326
GENODE_RPC
(
Rpc_affinity,
void,
affinity,
Thread_capability,
Affinity::
Location)
;
327
GENODE_RPC
(
Rpc_trace_control,
Dataspace_capability,
trace_control)
;
328
GENODE_RPC
(
Rpc_trace_control_index,
unsigned
,
trace_control_index,
Thread_capability)
;
329
GENODE_RPC
(
Rpc_trace_buffer,
Dataspace_capability,
trace_buffer,
Thread_capability)
;
330
GENODE_RPC
(
Rpc_trace_policy,
Dataspace_capability,
trace_policy,
Thread_capability)
;
331
GENODE_RPC
(
Rpc_ref_account,
int,
ref_account,
Cpu_session_capability)
;
332
GENODE_RPC
(
Rpc_transfer_quota,
int,
transfer_quota,
Cpu_session_capability,
size_t)
;
333
GENODE_RPC
(
Rpc_quota,
Quota,
quota)
;
334
335
/*
336
* `GENODE_RPC_INTERFACE` declaration done manually
337
*
338
* The number of RPC functions of this interface exceeds the maximum
339
* number of elements supported by `Meta::Type_list`. Therefore, we
340
* construct the type list by hand using nested type tuples instead
341
* of employing the convenience macro `GENODE_RPC_INTERFACE`.
342
*/
343
typedef
Meta::
Type_tuple<
Rpc_create_thread
,
344
Meta::
Type_tuple<
Rpc_utcb
,
345
Meta::
Type_tuple<
Rpc_kill_thread
,
346
Meta::
Type_tuple<
Rpc_set_pager
,
347
Meta::
Type_tuple<
Rpc_start
,
348
Meta::
Type_tuple<
Rpc_pause
,
349
Meta::
Type_tuple<
Rpc_resume
,
350
Meta::
Type_tuple<
Rpc_cancel_blocking
,
351
Meta::
Type_tuple<
Rpc_set_state
,
352
Meta::
Type_tuple<
Rpc_get_state
,
353
Meta::
Type_tuple<
Rpc_exception_handler
,
354
Meta::
Type_tuple<
Rpc_single_step
,
355
Meta::
Type_tuple<
Rpc_affinity_space
,
356
Meta::
Type_tuple<
Rpc_affinity
,
357
Meta::
Type_tuple<
Rpc_trace_control
,
358
Meta::
Type_tuple<
Rpc_trace_control_index
,
359
Meta::
Type_tuple<
Rpc_trace_buffer
,
360
Meta::
Type_tuple<
Rpc_trace_policy
,
361
Meta::
Type_tuple<
Rpc_ref_account
,
362
Meta::
Type_tuple<
Rpc_transfer_quota
,
363
Meta::
Type_tuple<
Rpc_quota
,
364
Meta::
Empty
>
365
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
Rpc_functions
;
366
}
;
367
368
struct
Genode::
Cpu_session::
Quota
369
{
370
size_t super_period_us;
371
size_t us;
372
}
;
373
374
#
endif /* _INCLUDE__CPU_SESSION__CPU_SESSION_H_ */