summaryrefslogtreecommitdiff
path: root/cesar/lib/slab.h
blob: c19ab9128c52325b868d48fca9b317bd4ecd5235 (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
123
124
125
126
127
128
129
130
131
132
#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/blame.h"
#include "lib/list.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;
    /** Number of object per slab. */
    uint object_per_slab;
    /** Offset of the first object in a slab. */
    uint object_offset_first;
    /** Offset of the next objects after the first. */
    uint object_offset;
    /** Partially used slabs. */
    list_t partial;
    /** Full slabs. */
    uint full_nb;
    /** 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 */