1 |
/* Copyright (C) 2003 Free Software Foundation, Inc. |
/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. |
2 |
Written by Johan Rydberg. |
Written by Johan Rydberg. |
3 |
|
|
4 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
65 |
union hurd_bufctl *free_list; |
union hurd_bufctl *free_list; |
66 |
}; |
}; |
67 |
|
|
68 |
|
/* Allocate a buffer in *PTR of size SIZE which must be a power of 2 |
69 |
|
and self aligned (i.e. aligned on a SIZE byte boundary) for slab |
70 |
|
space SPACE. Return 0 on success, an error code on failure. */ |
71 |
|
static error_t |
72 |
|
allocate_buffer (struct hurd_slab_space *space, size_t size, void **ptr) |
73 |
|
{ |
74 |
|
if (space->allocate_buffer) |
75 |
|
return space->allocate_buffer (space->hook, getpagesize (), ptr); |
76 |
|
else |
77 |
|
{ |
78 |
|
*ptr = mmap (NULL, getpagesize (), PROT_READ|PROT_WRITE, |
79 |
|
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
80 |
|
if (*ptr == MAP_FAILED) |
81 |
|
return errno; |
82 |
|
else |
83 |
|
return 0; |
84 |
|
} |
85 |
|
} |
86 |
|
|
87 |
|
/* Deallocate buffer BUFFER of size SIZE which was allocated for slab |
88 |
|
space SPACE. Return 0 on success, an error code on failure. */ |
89 |
|
static error_t |
90 |
|
deallocate_buffer (struct hurd_slab_space *space, void *buffer, size_t size) |
91 |
|
{ |
92 |
|
if (space->deallocate_buffer) |
93 |
|
return space->deallocate_buffer (space->hook, buffer, size); |
94 |
|
else |
95 |
|
{ |
96 |
|
if (munmap (buffer, size) == -1) |
97 |
|
return errno; |
98 |
|
else |
99 |
|
return 0; |
100 |
|
} |
101 |
|
} |
102 |
|
|
103 |
/* Insert SLAB into the list of slabs in SPACE. SLAB is expected to |
/* Insert SLAB into the list of slabs in SPACE. SLAB is expected to |
104 |
be complete (so it will be inserted at the end). */ |
be complete (so it will be inserted at the end). */ |
177 |
in front of it), get address by masking with page size. |
in front of it), get address by masking with page size. |
178 |
This frees the slab and all its buffers, since they live on |
This frees the slab and all its buffers, since they live on |
179 |
the same page. */ |
the same page. */ |
180 |
err = munmap |
err = deallocate_buffer (space, (void *) (((uintptr_t) s) |
181 |
((void *) (((uintptr_t) s) & ~(getpagesize () - 1)), |
& ~(getpagesize () - 1)), |
182 |
getpagesize ()); |
getpagesize ()); |
183 |
if (err) |
if (err) |
184 |
break; |
break; |
185 |
__hurd_slab_nr_pages--; |
__hurd_slab_nr_pages--; |
234 |
static error_t |
static error_t |
235 |
grow (struct hurd_slab_space *space) |
grow (struct hurd_slab_space *space) |
236 |
{ |
{ |
237 |
|
error_t err; |
238 |
struct hurd_slab *new_slab; |
struct hurd_slab *new_slab; |
239 |
union hurd_bufctl *bufctl; |
union hurd_bufctl *bufctl; |
240 |
int nr_objs, i; |
int nr_objs, i; |
246 |
if (!space->initialized) |
if (!space->initialized) |
247 |
init_space (space); |
init_space (space); |
248 |
|
|
249 |
p = mmap (NULL, getpagesize (), PROT_READ|PROT_WRITE, |
err = allocate_buffer (space, getpagesize (), &p); |
250 |
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
if (err) |
251 |
if (p == MAP_FAILED) |
return err; |
252 |
return errno; |
|
253 |
__hurd_slab_nr_pages++; |
__hurd_slab_nr_pages++; |
254 |
|
|
255 |
new_slab = (p + getpagesize () - sizeof (struct hurd_slab)); |
new_slab = (p + getpagesize () - sizeof (struct hurd_slab)); |
279 |
(*space->destructor) (space->hook, buffer); |
(*space->destructor) (space->hook, buffer); |
280 |
} |
} |
281 |
|
|
282 |
munmap (p, getpagesize ()); |
deallocate_buffer (space, p, getpagesize ()); |
283 |
return err; |
return err; |
284 |
} |
} |
285 |
} |
} |
305 |
/* Initialize the slab space SPACE. */ |
/* Initialize the slab space SPACE. */ |
306 |
error_t |
error_t |
307 |
hurd_slab_init (hurd_slab_space_t space, size_t size, size_t alignment, |
hurd_slab_init (hurd_slab_space_t space, size_t size, size_t alignment, |
308 |
|
hurd_slab_allocate_buffer_t allocate_buffer, |
309 |
|
hurd_slab_deallocate_buffer_t deallocate_buffer, |
310 |
hurd_slab_constructor_t constructor, |
hurd_slab_constructor_t constructor, |
311 |
hurd_slab_destructor_t destructor, |
hurd_slab_destructor_t destructor, |
312 |
void *hook) |
void *hook) |
336 |
if (err) |
if (err) |
337 |
return err; |
return err; |
338 |
|
|
339 |
|
space->allocate_buffer = allocate_buffer; |
340 |
|
space->deallocate_buffer = deallocate_buffer; |
341 |
space->constructor = constructor; |
space->constructor = constructor; |
342 |
space->destructor = destructor; |
space->destructor = destructor; |
343 |
space->hook = hook; |
space->hook = hook; |
351 |
constructor and destructor. ALIGNMENT can be zero. */ |
constructor and destructor. ALIGNMENT can be zero. */ |
352 |
error_t |
error_t |
353 |
hurd_slab_create (size_t size, size_t alignment, |
hurd_slab_create (size_t size, size_t alignment, |
354 |
|
hurd_slab_allocate_buffer_t allocate_buffer, |
355 |
|
hurd_slab_deallocate_buffer_t deallocate_buffer, |
356 |
hurd_slab_constructor_t constructor, |
hurd_slab_constructor_t constructor, |
357 |
hurd_slab_destructor_t destructor, |
hurd_slab_destructor_t destructor, |
358 |
void *hook, |
void *hook, |
365 |
if (!space) |
if (!space) |
366 |
return ENOMEM; |
return ENOMEM; |
367 |
|
|
368 |
err = hurd_slab_init (space, size, alignment, constructor, destructor, hook); |
err = hurd_slab_init (space, size, alignment, |
369 |
|
allocate_buffer, deallocate_buffer, |
370 |
|
constructor, destructor, hook); |
371 |
if (err) |
if (err) |
372 |
{ |
{ |
373 |
free (space); |
free (space); |