1
/*
2
* \brief Lock-guarded allocator interface
3
* \author Norman Feske
4
* \date 2008-08-05
5
*/
6
7
/*
8
* Copyright (C) 2008-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__SYNC_ALLOCATOR_H_
15
#
define _INCLUDE__BASE__SYNC_ALLOCATOR_H_
16
17
#
include <base/allocator.h>
18
#
include <base/lock.h>
19
20
namespace
Genode {
21
22
template
<
typename
>
class
Synchronized_allocator;
23
template
<
typename
>
class
Synchronized_range_allocator;
24
}
25
26
27
/**
28
* Lock-guarded allocator
29
*
30
* This class wraps the complete `Allocator` interface while
31
* preventing concurrent calls to the wrapped allocator implementation.
32
*
33
* \param ALLOCATOR_IMPL class implementing the `Allocator`
34
* interface
35
*/
36
template
<
typename
ALLOCATOR_IMPL
>
37
class
Genode::
Synchronized_allocator :
public
Allocator
38
{
39
private
:
40
41
Lock _default_lock;
42
Lock *
_lock;
43
ALLOCATOR_IMPL _alloc;
44
45
public
:
46
47
/**
48
* Constructor
49
*
50
* This constructor uses an embedded lock for synchronizing the
51
* access to the allocator.
52
*/
53
Synchronized_allocator(
)
54
:
_lock(
&
_default_lock)
{
}
55
56
/**
57
* Constructor
58
*
59
* This constructor uses an embedded lock for synchronizing the
60
* access to the allocator.
61
*/
62
explicit
Synchronized_allocator(
Allocator *
metadata_alloc
)
63
:
_lock(
&
_default_lock)
,
_alloc(
metadata_alloc)
{
}
64
65
/**
66
* Return reference to wrapped (non-thread-safe) allocator
67
*
68
* This is needed, for example, if the wrapped allocator implements
69
* methods in addition to the Range_allocator interface.
70
*/
71
ALLOCATOR_IMPL *
raw(
)
{
return
&
_alloc
;
}
72
73
/*************************
74
** Allocator interface **
75
*************************/
76
77
bool
alloc(
size_t
size
,
void *
*
out_addr
)
override
78
{
79
Lock::
Guard
lock_guard(
*
_lock
)
;
80
return
_alloc.
alloc(
size,
out_addr)
;
81
}
82
83
void
free(
void *
addr
,
size_t
size
)
override
84
{
85
Lock::
Guard
lock_guard(
*
_lock
)
;
86
_alloc.
free(
addr,
size)
;
87
}
88
89
size_t
consumed(
)
const
override
90
{
91
Lock::
Guard
lock_guard(
*
_lock
)
;
92
return
_alloc.
consumed(
)
;
93
}
94
95
size_t
overhead(
size_t
size
)
const
override
96
{
97
Lock::
Guard
lock_guard(
*
_lock
)
;
98
return
_alloc.
overhead(
size)
;
99
}
100
101
bool
need_size_for_free(
)
const
override
102
{
103
Lock::
Guard
lock_guard(
*
_lock
)
;
104
return
_alloc.
need_size_for_free(
)
;
105
}
106
}
;
107
108
109
/**
110
* Lock-guarded range allocator
111
*
112
* This class wraps the complete `Range_allocator` interface while
113
* preventing concurrent calls to the wrapped allocator implementation.
114
*
115
* \param ALLOCATOR_IMPL class implementing the `Range_allocator`
116
* interface
117
*/
118
template
<
typename
ALLOCATOR_IMPL
>
119
class
Genode::
Synchronized_range_allocator :
public
Range_allocator
120
{
121
private
:
122
123
Lock _default_lock;
124
Lock *
_lock;
125
ALLOCATOR_IMPL _alloc;
126
127
public
:
128
129
/**
130
* Constructor
131
*
132
* This constructor uses an embedded lock for synchronizing the
133
* access to the allocator.
134
*/
135
Synchronized_range_allocator(
)
136
:
_lock(
&
_default_lock)
{
}
137
138
/**
139
* Constructor
140
*
141
* This constructor uses an embedded lock for synchronizing the
142
* access to the allocator.
143
*/
144
explicit
Synchronized_range_allocator(
Allocator *
metadata_alloc
)
145
:
_lock(
&
_default_lock)
,
_alloc(
metadata_alloc)
{
}
146
147
/**
148
* Constructor
149
*
150
* \param lock use specified lock rather then an embedded lock for
151
* synchronization
152
*
153
* This constructor is useful if multiple allocators must be
154
* synchronized with each other. In such as case, the shared
155
* lock can be passed to each `Synchronized_range_allocator`
156
* instance.
157
*/
158
Synchronized_range_allocator(
Lock *
lock
,
Allocator *
metadata_alloc
)
159
:
_lock(
lock)
,
_alloc(
metadata_alloc)
{
}
160
161
/**
162
* Return reference to wrapped (non-thread-safe) allocator
163
*
164
* This is needed, for example, if the wrapped allocator implements
165
* methods in addition to the Range_allocator interface.
166
*
167
* NOTE: Synchronize accesses to the raw allocator by facilitating
168
* the lock() method.
169
*/
170
ALLOCATOR_IMPL *
raw(
)
{
return
&
_alloc
;
}
171
172
/**
173
* Return reference to synchronization lock
174
*/
175
Lock *
lock(
)
{
return
_lock
;
}
176
177
178
/*************************
179
** Allocator interface **
180
*************************/
181
182
bool
alloc(
size_t
size
,
void *
*
out_addr
)
override
183
{
184
Lock::
Guard
lock_guard(
*
_lock
)
;
185
return
_alloc.
alloc(
size,
out_addr)
;
186
}
187
188
void
free(
void *
addr
,
size_t
size
)
override
189
{
190
Lock::
Guard
lock_guard(
*
_lock
)
;
191
_alloc.
free(
addr,
size)
;
192
}
193
194
size_t
consumed(
)
const
override
195
{
196
Lock::
Guard
lock_guard(
*
_lock
)
;
197
return
_alloc.
consumed(
)
;
198
}
199
200
size_t
overhead(
size_t
size
)
const
override
201
{
202
Lock::
Guard
lock_guard(
*
_lock
)
;
203
return
_alloc.
overhead(
size)
;
204
}
205
206
bool
need_size_for_free(
)
const
override
207
{
208
Lock::
Guard
lock_guard(
*
_lock
)
;
209
return
_alloc.
need_size_for_free(
)
;
210
}
211
212
213
/*******************************
214
** Range-allocator interface **
215
*******************************/
216
217
int
add_range(
addr_t
base
,
size_t
size
)
override
218
{
219
Lock::
Guard
lock_guard(
*
_lock
)
;
220
return
_alloc.
add_range(
base,
size)
;
221
}
222
223
int
remove_range(
addr_t
base
,
size_t
size
)
override
224
{
225
Lock::
Guard
lock_guard(
*
_lock
)
;
226
return
_alloc.
remove_range(
base,
size)
;
227
}
228
229
Alloc_return
alloc_aligned(
size_t
size
,
void *
*
out_addr
,
int
align
=
0
,
230
addr_t
from
=
0
,
addr_t
to
=
~
0UL
)
override
231
{
232
Lock::
Guard
lock_guard(
*
_lock
)
;
233
return
_alloc.
alloc_aligned(
size,
out_addr,
align,
from,
to)
;
234
}
235
236
Alloc_return
alloc_addr(
size_t
size
,
addr_t
addr
)
override
237
{
238
Lock::
Guard
lock_guard(
*
_lock
)
;
239
return
_alloc.
alloc_addr(
size,
addr)
;
240
}
241
242
void
free(
void *
addr
)
override
243
{
244
Lock::
Guard
lock_guard(
*
_lock
)
;
245
_alloc.
free(
addr)
;
246
}
247
248
size_t
avail(
)
const
override
249
{
250
Lock::
Guard
lock_guard(
*
_lock
)
;
251
return
_alloc.
avail(
)
;
252
}
253
254
bool
valid_addr(
addr_t
addr
)
const
override
255
{
256
Lock::
Guard
lock_guard(
*
_lock
)
;
257
return
_alloc.
valid_addr(
addr)
;
258
}
259
}
;
260
261
#
endif /* _INCLUDE__BASE__SYNC_ALLOCATOR_H_ */