1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
/* slab.h - The GNU Hurd slab allocator interface.
Copyright (C) 2003, 2005 Free Software Foundation, Inc.
Written by Marcus Brinkmann <marcus@gnu.org>
This file is part of the GNU Hurd.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _HURD_SLAB_H
#define _HURD_SLAB_H 1
#include <errno.h>
#include <stdbool.h>
#include <cthreads.h>
/* Allocate a buffer in *PTR of size SIZE which must be a power of 2
and self aligned (i.e. aligned on a SIZE byte boundary). HOOK is
as provided to hurd_slab_create. Return 0 on success, an error
code on failure. */
typedef error_t (*hurd_slab_allocate_buffer_t) (void *hook, size_t size,
void **ptr);
/* Deallocate buffer BUFFER of size SIZE. HOOK is as provided to
hurd_slab_create. */
typedef error_t (*hurd_slab_deallocate_buffer_t) (void *hook, void *buffer,
size_t size);
/* Initialize the slab object pointed to by OBJECT. HOOK is as
provided to hurd_slab_create. */
typedef error_t (*hurd_slab_constructor_t) (void *hook, void *object);
/* Destroy the slab object pointed to by OBJECT. HOOK is as provided
to hurd_slab_create. */
typedef void (*hurd_slab_destructor_t) (void *hook, void *object);
/* The type of a slab space.
The structure is divided into two parts: the first is only used
while the slab space is constructed. Its fields are either
initialized by a static initializer (HURD_SLAB_SPACE_INITIALIZER)
or by the hurd_slab_create function. The initialization of the
space is delayed until the first allocation. After that only the
second part is used. */
typedef struct hurd_slab_space *hurd_slab_space_t;
struct hurd_slab_space
{
/* First part. Used when initializing slab space object. */
/* True if slab space has been initialized. */
bool initialized;
/* Protects this structure, along with all the slabs. No need to
delay initialization of this field. */
struct mutex lock;
/* The size and alignment of objects allocated using this slab
space. These to fields are used to calculate the final object
size, which is put in SIZE (defined below). */
size_t requested_size;
size_t requested_align;
/* The size of each slab. */
size_t slab_size;
/* The buffer allocator. */
hurd_slab_allocate_buffer_t allocate_buffer;
/* The buffer deallocator. */
hurd_slab_deallocate_buffer_t deallocate_buffer;
/* The constructor. */
hurd_slab_constructor_t constructor;
/* The destructor. */
hurd_slab_destructor_t destructor;
/* The user's private data. */
void *hook;
/* Second part. Runtime information for the slab space. */
struct hurd_slab *slab_first;
struct hurd_slab *slab_last;
/* In the doubly-linked list of slabs, empty slabs come first, after
that the slabs that have some buffers allocated, and finally the
complete slabs (refcount == 0). FIRST_FREE points to the first
non-empty slab. */
struct hurd_slab *first_free;
/* For easy checking, this holds the value the reference counter
should have for an empty slab. */
int full_refcount;
/* The size of one object. Should include possible alignment as
well as the size of the bufctl structure. */
size_t size;
};
/* Static initializer. TYPE is used to get size and alignment of
objects the slab space will be used to allocate. ALLOCATE_BUFFER
may be NULL in which case mmap is called. DEALLOCATE_BUFFER may be
NULL in which case munmap is called. CTOR and DTOR are the slab's
object constructor and destructor, respectivly and may be NULL if
not required. HOOK is passed as user data to the constructor and
destructor. */
#define HURD_SLAB_SPACE_INITIALIZER(TYPE, ALLOC, DEALLOC, CTOR, \
DTOR, HOOK) \
{ \
false, \
PTHREAD_MUTEX_INITIALIZER, \
sizeof (TYPE), \
__alignof__ (TYPE), \
ALLOC, \
DEALLOC, \
CTOR, \
DTOR, \
HOOK \
/* The rest of the structure will be filled with zeros, \
which is good for us. */ \
}
/* Create a new slab space with the given object size, alignment,
constructor and destructor. ALIGNMENT can be zero.
ALLOCATE_BUFFER may be NULL in which case mmap is called.
DEALLOCATE_BUFFER may be NULL in which case munmap is called. CTOR
and DTOR are the slabs object constructor and destructor,
respectivly and may be NULL if not required. HOOK is passed as the
first argument to the constructor and destructor. */
error_t hurd_slab_create (size_t size, size_t alignment,
hurd_slab_allocate_buffer_t allocate_buffer,
hurd_slab_deallocate_buffer_t deallocate_buffer,
hurd_slab_constructor_t constructor,
hurd_slab_destructor_t destructor,
void *hook,
hurd_slab_space_t *space);
/* Destroy all objects and the slab space SPACE. If there were no
outstanding allocations free the slab space. Returns EBUSY if
there are still allocated objects in the slab space. The dual of
hurd_slab_create. */
error_t hurd_slab_free (hurd_slab_space_t space);
/* Like hurd_slab_create, but does not allocate storage for the slab. */
error_t hurd_slab_init (hurd_slab_space_t space, size_t size, size_t alignment,
hurd_slab_allocate_buffer_t allocate_buffer,
hurd_slab_deallocate_buffer_t deallocate_buffer,
hurd_slab_constructor_t constructor,
hurd_slab_destructor_t destructor,
void *hook);
/* Destroy all objects and the slab space SPACE. Returns EBUSY if
there are still allocated objects in the slab. The dual of
hurd_slab_init. */
error_t hurd_slab_destroy (hurd_slab_space_t space);
/* Allocate a new object from the slab space SPACE. */
error_t hurd_slab_alloc (hurd_slab_space_t space, void **buffer);
/* Deallocate the object BUFFER from the slab space SPACE. */
void hurd_slab_dealloc (hurd_slab_space_t space, void *buffer);
/* Create a more strongly typed slab interface a la a C++ template.
NAME is the name of the new slab class. NAME is used to synthesize
names for the class types and methods using the following rule: the
hurd_ namespace will prefix all method names followed by NAME
followed by an underscore and finally the method name. The
following are thus exposed:
Types:
struct hurd_NAME_slab_space
hurd_NAME_slab_space_t
error_t (*hurd_NAME_slab_constructor_t) (void *hook, element_type *buffer)
void (*hurd_NAME_slab_destructor_t) (void *hook, element_type *buffer)
Functions:
error_t hurd_NAME_slab_create (hurd_slab_allocate_buffer_t
allocate_buffer,
hurd_slab_deallocate_buffer_t
deallocate_buffer,
hurd_NAME_slab_constructor_t constructor,
hurd_NAME_slab_destructor_t destructor,
void *hook,
hurd_NAME_slab_space_t *space);
error_t hurd_NAME_slab_free (hurd_NAME_slab_space_t space);
error_t hurd_NAME_slab_init (hurd_NAME_slab_space_t space,
hurd_slab_allocate_buffer_t allocate_buffer,
hurd_slab_deallocate_buffer_t
deallocate_buffer,
hurd_NAME_slab_constructor_t constructor,
hurd_NAME_slab_destructor_t destructor,
void *hook);
error_t hurd_NAME_slab_destroy (hurd_NAME_slab_space_t space);
error_t hurd_NAME_slab_alloc (hurd_NAME_slab_space_t space,
element_type **buffer);
void hurd_NAME_slab_dealloc (hurd_NAME_slab_space_t space,
element_type *buffer);
ELEMENT_TYPE is the type of elements to store in the slab. If you
want the slab to contain struct foo, pass `struct foo' as the
ELEMENT_TYPE (not `struct foo *'!!!).
*/
#define SLAB_CLASS(name, element_type) \
struct hurd_##name##_slab_space \
{ \
struct hurd_slab_space space; \
}; \
typedef struct hurd_##name##_slab_space *hurd_##name##_slab_space_t; \
\
typedef error_t (*hurd_##name##_slab_constructor_t) (void *hook, \
element_type *buffer); \
\
typedef void (*hurd_##name##_slab_destructor_t) (void *hook, \
element_type *buffer); \
\
static inline error_t \
hurd_##name##_slab_create (hurd_slab_allocate_buffer_t allocate_buffer, \
hurd_slab_deallocate_buffer_t deallocate_buffer, \
hurd_##name##_slab_constructor_t constructor, \
hurd_##name##_slab_destructor_t destructor, \
void *hook, \
hurd_##name##_slab_space_t *space) \
{ \
union \
{ \
hurd_##name##_slab_constructor_t t; \
hurd_slab_constructor_t u; \
} con; \
union \
{ \
hurd_##name##_slab_destructor_t t; \
hurd_slab_destructor_t u; \
} des; \
union \
{ \
hurd_##name##_slab_space_t *t; \
hurd_slab_space_t *u; \
} foo; \
con.t = constructor; \
des.t = destructor; \
foo.t = space; \
\
return hurd_slab_create(sizeof (element_type), __alignof__ (element_type), \
allocate_buffer, deallocate_buffer, \
con.u, des.u, hook, foo.u); \
} \
\
static inline error_t \
hurd_##name##_slab_free (hurd_##name##_slab_space_t space) \
{ \
return hurd_slab_free (&space->space); \
} \
\
static inline error_t \
hurd_##name##_slab_init (hurd_##name##_slab_space_t space, \
hurd_slab_allocate_buffer_t allocate_buffer, \
hurd_slab_deallocate_buffer_t deallocate_buffer, \
hurd_##name##_slab_constructor_t constructor, \
hurd_##name##_slab_destructor_t destructor, \
void *hook) \
{ \
union \
{ \
hurd_##name##_slab_constructor_t t; \
hurd_slab_constructor_t u; \
} con; \
union \
{ \
hurd_##name##_slab_destructor_t t; \
hurd_slab_destructor_t u; \
} des; \
con.t = constructor; \
des.t = destructor; \
\
return hurd_slab_init (&space->space, \
sizeof (element_type), __alignof__ (element_type), \
allocate_buffer, deallocate_buffer, \
con.u, des.u, hook); \
} \
\
static inline error_t \
hurd_##name##_slab_destroy (hurd_##name##_slab_space_t space) \
{ \
return hurd_slab_destroy (&space->space); \
} \
\
static inline error_t \
hurd_##name##_slab_alloc (hurd_##name##_slab_space_t space, \
element_type **buffer) \
{ \
union \
{ \
element_type **e; \
void **v; \
} foo; \
foo.e = buffer; \
\
return hurd_slab_alloc (&space->space, foo.v); \
} \
\
static inline void \
hurd_##name##_slab_dealloc (hurd_##name##_slab_space_t space, \
element_type *buffer) \
{ \
union \
{ \
element_type *e; \
void *v; \
} foo; \
foo.e = buffer; \
\
hurd_slab_dealloc (&space->space, foo.v); \
}
#endif /* _HURD_SLAB_H */
|