summaryrefslogtreecommitdiff
path: root/cesar/lib/slab.h
blob: ebea8c473a2cfad3987eca3bb32745b3cf93516a (plain)
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
#ifndef lib_slab_h
#define lib_slab_h
/* Cesar project {{{
 *
 * Copyright (C) 2008 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    lib/slab.h
 * \brief   Slab allocator.
 * \ingroup lib
 *
 * Slab Allocator
 * ==============
 *
 * The slab allocator is a finer grain allocator.  It allocates memory using
 * the block allocator and slices the allocated blocks into smaller memory
 * buffers, all with the same size.
 *
 * It solves two problems:
 *
 *  - the need for an allocator with smaller allocation size than the block
 *    allocator,
 *  - reducing memory fragmentation.
 *
 * The allocation unit of this allocator is called an object.  Objects are
 * allocated from a cache.
 *
 * A cache is a storage of objects of the same type.  It allocates memory by
 * slabs, which corresponds here to blocks from the block allocator.  Slabs
 * are then sliced into objects.
 *
 * Differences from other slab allocators:
 *
 *  - does not try to cache constructed objects, only uses the memory
 *    allocation part of slab allocators benefits.
 *  - reference counting: an object can be referenced by several pointers, it
 *    will be deallocated once every references are released.
 *  - polymorphism: the cache structure is not needed to add or release a
 *    reference, therefore, it can be done without knowing the underlying
 *    type.
 */

#include "lib/restrack.h"

/**
 * Object destructor called just before the object memory is released.
 * \param  object  pointer to object data
 */
typedef void (*slab_object_destructor_t) (void *object);

/** The slab cache structure. */
struct slab_cache_t
{
    /** Cache name. */
    const char *name;
    /** Size of objects in the cache. */
    uint object_size;
    /** Destructor for objects in the cache. */
    slab_object_destructor_t object_destructor;
};
typedef struct slab_cache_t slab_cache_t;

BEGIN_DECLS

/**
 * Initialise the slab allocator.
 */
void
slab_init (void);

/**
 * Create a new slab cache.
 * \param  cache  cache structure
 * \param  name  cache name
 * \param  object_size  size of objects in the cache
 * \param  object_destructor  destructor for objects in the cache, or NULL if
 * none
 */
void
slab_cache_init (slab_cache_t *cache, const char *name, uint object_size,
                 slab_object_destructor_t object_destructor);

/**
 * Destroy a slab cache.
 * \param  cache  cache structure
 *
 * The cache must be empty.
 */
void
slab_cache_uninit (slab_cache_t *cache);

/**
 * Allocate an object from the slab cache.
 * \param  cache  cache structure
 * \return  the newly allocated object
 */
void *
slab_alloc_ (slab_cache_t *cache __FL);
#define slab_alloc(cache) slab_alloc_ ((cache) __fL)

/**
 * Add a reference to a slab cache allocated object.
 * \param  object  referenced object
 */
void
slab_addref_ (void *object __FL);
#define slab_addref(object) slab_addref_ ((object) __fL)

/**
 * Remove a reference to a slab cache allocated object.
 * \param  object  referenced object
 */
void
slab_release_ (void *object __FL);
#define slab_release(object) slab_release_ ((object) __fL)

END_DECLS

#endif /* lib_slab_h */