summaryrefslogtreecommitdiff
path: root/libhurd-slab/slab.h
diff options
context:
space:
mode:
Diffstat (limited to 'libhurd-slab/slab.h')
-rw-r--r--libhurd-slab/slab.h338
1 files changed, 338 insertions, 0 deletions
diff --git a/libhurd-slab/slab.h b/libhurd-slab/slab.h
new file mode 100644
index 00000000..d42fd4c3
--- /dev/null
+++ b/libhurd-slab/slab.h
@@ -0,0 +1,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 */