1
/*
2
* \brief Capability
3
* \author Norman Feske
4
* \date 2011-05-22
5
*
6
* A typed capability is a capability tied to one specifiec RPC interface
7
*/
8
9
/*
10
* Copyright (C) 2011-2013 Genode Labs GmbH
11
*
12
* This file is part of the Genode OS framework, which is distributed
13
* under the terms of the GNU General Public License version 2.
14
*/
15
16
#
ifndef _INCLUDE__BASE__CAPABILITY_H_
17
#
define _INCLUDE__BASE__CAPABILITY_H_
18
19
#
include <util/string.h>
20
#
include <base/rpc.h>
21
#
include <base/native_types.h>
22
23
namespace
Genode {
24
25
/**
26
* Forward declaration needed for internal interfaces of `Capability`
27
*/
28
class
Ipc_client;
29
30
31
/**
32
* Capability that is not associated with a specific RPC interface
33
*/
34
typedef
Native_capability Untyped_capability
;
35
36
template
<
typename
>
class
Capability;
37
38
template
<
typename
RPC_INTERFACE
>
39
Capability<
RPC_INTERFACE
>
reinterpret_cap_cast(
Untyped_capability const
&
)
;
40
41
template
<
typename
TO_RPC_INTERFACE
,
typename
FROM_RPC_INTERFACE
>
42
Capability<
TO_RPC_INTERFACE
>
static_cap_cast(
Capability<
FROM_RPC_INTERFACE
>
)
;
43
}
44
45
46
/**
47
* Capability referring to a specific RPC interface
48
*
49
* \param RPC_INTERFACE class containing the RPC interface declaration
50
*/
51
template
<
typename
RPC_INTERFACE
>
52
class
Genode::
Capability :
public
Untyped_capability
53
{
54
private
:
55
56
/**
57
* Insert RPC arguments into the message buffer
58
*/
59
template
<
typename
ATL
>
60
void
_marshal_args(
Ipc_client &
ipc_client
,
ATL &
args
)
const
;
61
62
void
_marshal_args(
Ipc_client &
,
Meta::
Empty &
)
const
{
}
63
64
/**
65
* Unmarshal single RPC argument from the message buffer
66
*/
67
template
<
typename
T
>
68
void
_unmarshal_result(
Ipc_client &
ipc_client
,
T &
arg
,
69
Meta::
Overload_selector<
Rpc_arg_out
>
)
const
;
70
71
template
<
typename
T
>
72
void
_unmarshal_result(
Ipc_client &
ipc_client
,
T &
arg
,
73
Meta::
Overload_selector<
Rpc_arg_inout
>
)
const
;
74
75
template
<
typename
T
>
76
void
_unmarshal_result(
Ipc_client &
,
T &
,
77
Meta::
Overload_selector<
Rpc_arg_in
>
)
const
{
}
78
79
/**
80
* Read RPC results from the message buffer
81
*/
82
template
<
typename
ATL
>
83
void
_unmarshal_results(
Ipc_client &
ipc_client
,
ATL &
args
)
const
;
84
85
void
_unmarshal_results(
Ipc_client &
,
Meta::
Empty &
)
const
{
}
86
87
/**
88
* Check RPC return code for the occurrence of exceptions
89
*
90
* A server-side exception is indicated by a non-zero exception
91
* code. Each exception code corresponds to an entry in the
92
* exception type list specified in the RPC function declaration.
93
* The `_check_for_exception` method template throws the
94
* exception type belonging to the received exception code.
95
*/
96
template
<
typename
EXC_TL
>
97
void
_check_for_exceptions(
Rpc_exception_code const
exc_code
,
98
Meta::
Overload_selector<
EXC_TL
>
)
const
99
{
100
enum
{
EXCEPTION_CODE =
RPC_EXCEPTION_BASE -
Meta::
Length<
EXC_TL
>
::
Value
}
;
101
102
if
(
exc_code ==
EXCEPTION_CODE)
103
throw
typename
EXC_TL::
Head(
)
;
104
105
_check_for_exceptions(
exc_code,
Meta::
Overload_selector<
typename
EXC_TL::
Tail
>
(
)
)
;
106
}
107
108
void
_check_for_exceptions(
Rpc_exception_code const
,
109
Meta::
Overload_selector<
Meta::
Empty
>
)
const
110
{
}
111
112
/**
113
* Perform RPC call, arguments passed a as nested `Ref_tuple` object
114
*/
115
template
<
typename
IF
>
116
void
_call(
typename
IF::
Client_args &
args
,
117
typename
IF::
Ret_type &
ret
)
const
;
118
119
/**
120
* Shortcut for querying argument types used in `call` methods
121
*/
122
template
<
typename
IF
,
unsigned
I
>
123
struct
Arg
124
{
125
typedef
typename
Meta::
Type_at<
typename
IF::
Client_args
,
I
>
::
Type Type;
126
}
;
127
128
template
<
typename
FROM_RPC_INTERFACE
>
129
Untyped_capability
130
_check_compatibility(
Capability<
FROM_RPC_INTERFACE
>
const
&
cap
)
const
131
{
132
FROM_RPC_INTERFACE *
from =
0;
133
RPC_INTERFACE *
to =
from;
134
(
void)
to;
135
return
cap
;
136
}
137
138
/**
139
* Wrapper for the return type instantiated by `call` overloads
140
*
141
* Each `call` overload creates an instance of the return value
142
* type as local variable. A reference to this variable is passed
143
* to the `_call` method, which will assign its value. Even
144
* though the variable does not need to be initialized prior the
145
* call of `_call`, the GCC will still complain "warning: ‘ret’ may
146
* be used uninitialized in this function". Wrapping the return
147
* value in a struct silences the compiler.
148
*/
149
template
<
typename
IF
>
150
struct
Return
151
{
152
typedef
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
153
Return_type;
154
155
volatile
Return_type _value;
156
Return_type &
value(
)
{
return
*
(
Return_type *
)
(
&
_value)
;
}
157
}
;
158
159
public
:
160
161
typedef
RPC_INTERFACE Rpc_interface
;
162
163
/**
164
* Constructor
165
*
166
* This implicit constructor checks at compile time for the
167
* compatibility of the source and target capability types. The
168
* construction is performed only if the target capability type is
169
* identical to or a base type of the source capability type.
170
*/
171
template
<
typename
FROM_RPC_INTERFACE
>
172
Capability(
Capability<
FROM_RPC_INTERFACE
>
const
&
cap
)
173
:
Untyped_capability(
_check_compatibility(
cap)
)
174
{
}
175
176
/**
177
* Default constructor creates invalid capability
178
*/
179
Capability(
)
{
}
180
181
template
<
typename
IF
>
182
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
183
call(
)
const
184
{
185
Meta::
Empty e;
186
Return<
IF
>
ret;
187
_call<
IF
>
(
e,
ret.
value(
)
)
;
188
return
ret.
value(
)
;
189
}
190
191
template
<
typename
IF
>
192
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
193
call(
typename
Arg<
IF
,
0
>
::
Type
v1
)
const
194
{
195
Meta::
Empty e;
196
typename
IF::
Client_args
args(
v1
,
e
)
;
197
Return<
IF
>
ret;
198
_call<
IF
>
(
args,
ret.
value(
)
)
;
199
return
ret.
value(
)
;
200
}
201
202
template
<
typename
IF
>
203
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
204
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
)
const
205
{
206
Meta::
Empty e;
207
typename
IF::
Client_args
args(
v1
,
v2
,
e
)
;
208
Return<
IF
>
ret;
209
_call<
IF
>
(
args,
ret.
value(
)
)
;
210
return
ret.
value(
)
;
211
}
212
213
template
<
typename
IF
>
214
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
215
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
,
216
typename
Arg<
IF
,
2
>
::
Type
v3
)
const
217
{
218
Meta::
Empty e;
219
typename
IF::
Client_args
args(
v1
,
v2
,
v3
,
e
)
;
220
Return<
IF
>
ret;
221
_call<
IF
>
(
args,
ret.
value(
)
)
;
222
return
ret.
value(
)
;
223
}
224
225
template
<
typename
IF
>
226
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
227
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
,
228
typename
Arg<
IF
,
2
>
::
Type
v3
,
typename
Arg<
IF
,
3
>
::
Type
v4
)
const
229
{
230
Meta::
Empty e;
231
typename
IF::
Client_args
args(
v1
,
v2
,
v3
,
v4
,
e
)
;
232
Return<
IF
>
ret;
233
_call<
IF
>
(
args,
ret.
value(
)
)
;
234
return
ret.
value(
)
;
235
}
236
237
template
<
typename
IF
>
238
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
239
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
,
240
typename
Arg<
IF
,
2
>
::
Type
v3
,
typename
Arg<
IF
,
3
>
::
Type
v4
,
241
typename
Arg<
IF
,
4
>
::
Type
v5
)
const
242
{
243
Meta::
Empty e;
244
typename
IF::
Client_args
args(
v1
,
v2
,
v3
,
v4
,
v5
,
e
)
;
245
Return<
IF
>
ret;
246
_call<
IF
>
(
args,
ret.
value(
)
)
;
247
return
ret.
value(
)
;
248
}
249
250
template
<
typename
IF
>
251
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
252
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
,
253
typename
Arg<
IF
,
2
>
::
Type
v3
,
typename
Arg<
IF
,
3
>
::
Type
v4
,
254
typename
Arg<
IF
,
4
>
::
Type
v5
,
typename
Arg<
IF
,
5
>
::
Type
v6
)
const
255
{
256
Meta::
Empty e;
257
typename
IF::
Client_args
args(
v1
,
v2
,
v3
,
v4
,
v5
,
v6
,
e
)
;
258
Return<
IF
>
ret;
259
_call<
IF
>
(
args,
ret.
value(
)
)
;
260
return
ret.
value(
)
;
261
}
262
263
template
<
typename
IF
>
264
typename
Trait::
Call_return<
typename
IF::
Ret_type
>
::
Type
265
call(
typename
Arg<
IF
,
0
>
::
Type
v1
,
typename
Arg<
IF
,
1
>
::
Type
v2
,
266
typename
Arg<
IF
,
2
>
::
Type
v3
,
typename
Arg<
IF
,
3
>
::
Type
v4
,
267
typename
Arg<
IF
,
4
>
::
Type
v5
,
typename
Arg<
IF
,
5
>
::
Type
v6
,
268
typename
Arg<
IF
,
6
>
::
Type
v7
)
const
269
{
270
Meta::
Empty e;
271
typename
IF::
Client_args
args(
v1
,
v2
,
v3
,
v4
,
v5
,
v6
,
v7
,
e
)
;
272
Return<
IF
>
ret;
273
_call<
IF
>
(
args,
ret.
value(
)
)
;
274
return
ret.
value(
)
;
275
}
276
}
;
277
278
279
/**
280
* Convert an untyped capability to a typed capability
281
*/
282
template
<
typename
RPC_INTERFACE
>
283
Genode::
Capability<
RPC_INTERFACE
>
284
Genode::
reinterpret_cap_cast(
Untyped_capability const
&
untyped_cap
)
285
{
286
/*
287
* The object layout of untyped and typed capabilities is identical.
288
* Hence we can just use it`s copy-constructors.
289
*/
290
Untyped_capability *
ptr =
const_cast<
Untyped_capability*
>
(
&
untyped_cap)
;
291
return
*
static_cast
<
Capability<
RPC_INTERFACE
>
*
>
(
ptr)
;
292
}
293
294
295
/**
296
* Convert capability type from an interface base type to an inherited
297
* interface type
298
*/
299
template
<
typename
TO_RPC_INTERFACE
,
typename
FROM_RPC_INTERFACE
>
300
Genode::
Capability<
TO_RPC_INTERFACE
>
301
Genode::
static_cap_cast(
Capability<
FROM_RPC_INTERFACE
>
cap
)
302
{
303
/* check interface compatibility */
304
(
void)
static_cast
<
TO_RPC_INTERFACE *
>
(
(
FROM_RPC_INTERFACE *
)
0)
;
305
306
return
reinterpret_cap_cast<
TO_RPC_INTERFACE
>
(
cap)
;
307
}
308
309
#
endif /* _INCLUDE__BASE__CAPABILITY_H_ */