1
/*
2
* \brief Child creation framework
3
* \author Norman Feske
4
* \date 2006-07-22
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__BASE__CHILD_H_
15
#
define _INCLUDE__BASE__CHILD_H_
16
17
#
include <base/rpc_server.h>
18
#
include <base/heap.h>
19
#
include <base/process.h>
20
#
include <base/service.h>
21
#
include <base/lock.h>
22
#
include <util/arg_string.h>
23
#
include <parent/parent.h>
24
25
namespace
Genode {
26
27
struct
Child_policy;
28
struct
Child;
29
}
30
31
32
/**
33
* Child policy interface
34
*
35
* A child-policy object is an argument to a `Child`. It is responsible for
36
* taking policy decisions regarding the parent interface. Most importantly,
37
* it defines how session requests are resolved and how session arguments
38
* are passed to servers when creating sessions.
39
*/
40
struct
Genode::
Child_policy
41
{
42
virtual
~
Child_policy(
)
{
}
43
44
/**
45
* Return process name of the child
46
*/
47
virtual
const
char *
name(
)
const
=
0
;
48
49
/**
50
* Determine service to provide a session request
51
*
52
* \return Service to be contacted for the new session, or
53
* 0 if session request could not be resolved
54
*/
55
virtual
Service *
resolve_session_request(
const
char *
/*service_name*/
,
56
const
char *
/*args*/
)
57
{
return
0
;
}
58
59
/**
60
* Apply transformations to session arguments
61
*/
62
virtual
void
filter_session_args(
const
char *
/*service*/
,
63
char *
/*args*/
,
size_t /*args_len*/
)
{
}
64
65
/**
66
* Register a service provided by the child
67
*
68
* \param name service name
69
* \param root interface for creating sessions for the service
70
* \param alloc allocator to be used for child-specific
71
* meta-data allocations
72
* \return true if announcement succeeded, or false if
73
* child is not permitted to announce service
74
*/
75
virtual
bool
announce_service(
const
char *
/*name*/
,
76
Root_capability /*root*/
,
77
Allocator *
/*alloc*/
,
78
Server *
/*server*/
)
79
{
return
false
;
}
80
81
/**
82
* Apply session affinity policy
83
*
84
* \param affinity affinity passed along with a session request
85
* \return affinity subordinated to the child policy
86
*/
87
virtual
Affinity
filter_session_affinity(
Affinity const
&
affinity
)
88
{
89
return
affinity
;
90
}
91
92
/**
93
* Unregister services that had been provided by the child
94
*/
95
virtual
void
unregister_services(
)
{
}
96
97
/**
98
* Exit child
99
*/
100
virtual
void
exit(
int
exit_value
)
101
{
102
PDBG(
"child \"
%
s\" exited with exit value %d"
,
name(
)
,
exit_value)
;
103
}
104
105
/**
106
* Reference RAM session
107
*
108
* The RAM session returned by this method is used for session-quota
109
* transfers.
110
*/
111
virtual
Ram_session *
ref_ram_session(
)
{
return
env(
)
->
ram_session(
)
;
}
112
virtual
Ram_session_capability
ref_ram_cap(
)
const
{
return
env(
)
->
ram_session_cap(
)
;
}
113
114
/**
115
* Respond to the release of resources by the child
116
*
117
* This method is called when the child confirms the release of
118
* resources in response to a yield request.
119
*/
120
virtual
void
yield_response(
)
{
}
121
122
/**
123
* Take action on additional resource needs by the child
124
*/
125
virtual
void
resource_request(
Parent::
Resource_args const
&
)
{
}
126
}
;
127
128
129
/**
130
* Implementation of the parent interface that supports resource trading
131
*
132
* There are three possible cases of how a session can be provided to
133
* a child: The service is implemented locally, the session was obtained by
134
* asking our parent, or the session is provided by one of our children.
135
*
136
* These types must be differentiated for the quota management when a child
137
* issues the closing of a session or transfers quota via our parent
138
* interface.
139
*
140
* If we close a session to a local service, we transfer the session quota
141
* from our own account to the client.
142
*
143
* If we close a parent session, we receive the session quota on our own
144
* account and must transfer this amount to the session-closing child.
145
*
146
* If we close a session provided by a server child, we close the session
147
* at the server, transfer the session quota from the server`s RAM session
148
* to our account, and subsequently transfer the same amount from our
149
* account to the client.
150
*/
151
class
Genode::
Child :
protected
Rpc_object<
Parent
>
152
{
153
private
:
154
155
class
Session;
156
157
/* PD session representing the protection domain of the child */
158
Pd_session_capability _pd;
159
Pd_session_client _pd_session_client;
160
161
/* RAM session that contains the quota of the child */
162
Ram_session_capability _ram;
163
Ram_session_client _ram_session_client;
164
165
/* CPU session that contains the quota of the child */
166
Cpu_session_capability _cpu;
167
168
/* RM session representing the address space of the child */
169
Rm_session_capability _rm;
170
171
/* Services where the PD, RAM, CPU, and RM resources come from */
172
Service &
_pd_service;
173
Service &
_ram_service;
174
Service &
_cpu_service;
175
Service &
_rm_service;
176
177
/* heap for child-specific allocations using the child`s quota */
178
Heap _heap;
179
180
Rpc_entrypoint *
_entrypoint;
181
Parent_capability _parent_cap;
182
183
/* child policy */
184
Child_policy *
_policy;
185
186
/* sessions opened by the child */
187
Lock _lock;
/* protect list manipulation */
188
Object_pool<
Session
>
_session_pool;
189
List<
Session
>
_session_list;
190
191
/* server role */
192
Server _server;
193
194
/* session-argument buffer */
195
char _args[Parent::
Session_args::
MAX_SIZE]
;
196
197
/* signal handlers registered by the child */
198
Signal_context_capability _resource_avail_sigh;
199
Signal_context_capability _yield_sigh;
200
201
/* arguments fetched by the child in response to a yield signal */
202
Lock _yield_request_lock;
203
Resource_args _yield_request_args;
204
205
Process _process;
206
207
/**
208
* Attach session information to a child
209
*
210
* \throw Ram_session::Quota_exceeded the child`s heap partition cannot
211
* hold the session meta data
212
*/
213
void
_add_session(
const
Session &
s
)
;
214
215
/**
216
* Close session and revert quota donation associated with it
217
*/
218
void
_remove_session(
Session *
s
)
;
219
220
void
_close(
Session *
s
)
;
221
222
/**
223
* Return service interface targetting the parent
224
*
225
* The service returned by this method is used as default
226
* provider for the RAM, CPU, and RM resources of the child. It is
227
* solely used for targeting resource donations during
228
* `Parent::upgrade_quota()` calls.
229
*/
230
static
Service *
_parent_service(
)
;
231
232
public
:
233
234
/**
235
* Constructor
236
*
237
* \param elf_ds dataspace containing the binary
238
* \param pd PD session representing the protection domain
239
* \param ram RAM session with the child`s quota
240
* \param cpu CPU session with the child`s quota
241
* \param rm RM session representing the address space
242
* of the child
243
* \param entrypoint server entrypoint to serve the parent interface
244
* \param policy child policy
245
* \param pd_service provider of the `pd` session
246
* \param ram_service provider of the `ram` session
247
* \param cpu_service provider of the `cpu` session
248
* \param rm_service provider of the `rm` session
249
*
250
* If assigning a separate entry point to each child, the host of
251
* multiple children is able to handle a blocking invocation of
252
* the parent interface of one child while still maintaining the
253
* service to other children, each having an independent entry
254
* point.
255
*
256
* The `ram_service`, `cpu_service`, and `rm_service` arguments are
257
* needed to direct quota upgrades referring to the resources of
258
* the child environment. By default, we expect that these
259
* resources are provided by the parent.
260
*/
261
Child(
Dataspace_capability
elf_ds
,
262
Pd_session_capability
pd
,
263
Ram_session_capability
ram
,
264
Cpu_session_capability
cpu
,
265
Rm_session_capability
rm
,
266
Rpc_entrypoint *
entrypoint
,
267
Child_policy *
policy
,
268
Service &
pd_service
=
*
_parent_service(
)
,
269
Service &
ram_service
=
*
_parent_service(
)
,
270
Service &
cpu_service
=
*
_parent_service(
)
,
271
Service &
rm_service
=
*
_parent_service(
)
)
;
272
273
/**
274
* Destructor
275
*
276
* On destruction of a child, we close all sessions of the child to
277
* other services.
278
*/
279
virtual
~
Child(
)
;
280
281
/**
282
* Return heap that uses the child`s quota
283
*/
284
Allocator *
heap(
)
{
return
&
_heap
;
}
285
286
Pd_session_capability
pd_session_cap(
)
const
{
return
_pd
;
}
287
Ram_session_capability
ram_session_cap(
)
const
{
return
_ram
;
}
288
Cpu_session_capability
cpu_session_cap(
)
const
{
return
_cpu
;
}
289
Rm_session_capability
rm_session_cap(
)
const
{
return
_rm
;
}
290
Parent_capability
parent_cap(
)
const
{
return
cap(
)
;
}
291
292
/**
293
* Discard all sessions to specified service
294
*
295
* When this method is called, we assume the server protection
296
* domain to be dead and all that all server quota was already
297
* transferred back to our own `env()->ram_session()` account. Note
298
* that the specified server object may not exist anymore. We do
299
* not de-reference the server argument in here!
300
*/
301
void
revoke_server(
const
Server *
server
)
;
302
303
/**
304
* Instruct the child to yield resources
305
*
306
* By calling this method, the child will be notified about the
307
* need to release the specified amount of resources. For more
308
* details about the protocol between a child and its parent,
309
* refer to the description given in `parent/parent.h`.
310
*/
311
void
yield(
Resource_args const
&
args
)
;
312
313
/**
314
* Notify the child about newly available resources
315
*/
316
void
notify_resource_avail(
)
const
;
317
318
319
/**********************
320
** Parent interface **
321
**********************/
322
323
void
announce(
Service_name const
&
,
Root_capability
)
override
;
324
Session_capability
session(
Service_name const
&
,
Session_args const
&
,
325
Affinity const
&
)
override
;
326
void
upgrade(
Session_capability
,
Upgrade_args const
&
)
override
;
327
void
close(
Session_capability
)
override
;
328
void
exit(
int
)
override
;
329
Thread_capability
main_thread_cap(
)
const
override
;
330
void
resource_avail_sigh(
Signal_context_capability
)
override
;
331
void
resource_request(
Resource_args const
&
)
override
;
332
void
yield_sigh(
Signal_context_capability
)
override
;
333
Resource_args
yield_request(
)
override
;
334
void
yield_response(
)
override
;
335
}
;
336
337
#
endif /* _INCLUDE__BASE__CHILD_H_ */