summaryrefslogtreecommitdiff
path: root/sos-code-article6.5/sos/kmem_slab.h
blob: 1f28ff9f659bd57eb61b518d6c97259dab5ffa87 (plain) (blame)
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
/* Copyright (C) 2000 Thomas Petazzoni
   Copyright (C) 2004 David Decotigny

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   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 General Public License for more details.
   
   You should have received a copy of the GNU 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 _SOS_KMEM_SLAB_H_
#define _SOS_KMEM_SLAB_H_

/**
 * @file kmem_slab.h
 *
 * Kernel Memory Allocator based on Bonwick's slab llocator (Solaris
 * 2.4, Linux 2.4). This allocator achieves good memory utilization
 * ratio (memory effectively used / memory requested) ie limited
 * fragmentation, while elegantly handling cache-effect considerations
 * (TLB locality through the notion of "cache" of slabs, and the
 * dcache utilization through the notion of cache colouring to
 * decrease the conflicts in the dcache for accesses to different data
 * in the same cache).
 *
 * This allocator relies on the range allocator (kmem_vmm.h) to
 * allocate the slabs, which itself relies on the slab allocator to
 * allocate its "range" data structures, thus leading to a
 * chicken-and-egg problem. We solve this problem by introducing the
 * notion of "min_free_objs" for the slab caches, in order for the cache
 * of ranges to always have enough ranges in reserve to complete the
 * range allocation before being urged to allocate a new slab of
 * ranges, which would require the allocation of a new range.
 *
 * Compared to Bonwick's recommendations, we don't handle ctor/dtor
 * routines on the objects, so that we can alter the objects once they
 * are set free. Thus, the list of free object is stored in the free
 * objects themselves, not alongside the objects (this also implies that
 * the SOS_KSLAB_CREATE_MAP flag below is meaningless). We also don't
 * implement the cache colouring (trivial to add, but we omit it for
 * readability reasons), and the only alignment constraint we respect
 * is that allocated objects are aligned on a 4B boundary: for other
 * alignment constraints, the user must integrate them in the
 * "object_size" parameter to "sos_kmem_cache_create()".
 *
 * References :
 * - J. Bonwick's paper, "The slab allocator: An object-caching kernel
 *   memory allocator", In USENIX Summer 1994 Technical Conference
 * - The bible, aka "Unix internals : the new frontiers" (section
 *   12.10), Uresh Vahalia, Prentice Hall 1996, ISBN 0131019082
 * - "The Linux slab allocator", B. Fitzgibbons,
 *   http://www.cc.gatech.edu/people/home/bradf/cs7001/proj2/
 * - The Kos, http://kos.enix.org/
 */
#include <sos/types.h>
#include <sos/errno.h>

/** Opaque data structure that defines a Cache of slabs */
struct sos_kslab_cache;

/** Opaque data structure that defines a slab. Exported only to
    kmem_vmm.h */
struct sos_kslab;

#include "kmem_vmm.h"


/** The maximum  allowed pages for each slab */
#define MAX_PAGES_PER_SLAB 32 /* 128 kB */


/**
 * Initialize the slab cache of slab caches, and prepare the cache of
 * kmem_range for kmem_vmm.
 *
 * @param kernel_core_base The virtual address of the first byte used
 * by the kernel code/data
 *
 * @param kernel_core_top The virtual address of the first byte after
 * the kernel code/data.
 *
 * @param sizeof_struct_range the size of the objects (aka "struct
 * sos_kmem_vmm_ranges") to be allocated in the cache of ranges
 *
 * @param first_struct_slab_of_caches (output value) the virtual
 * address of the first slab structure that gets allocated for the
 * cache of caches. The function actually manually allocate the first
 * slab of the cache of caches because of a chicken-and-egg thing. The
 * address of the slab is used by the kmem_vmm_setup routine to
 * finalize the allocation of the slab, in order for it to behave like
 * a real slab afterwards.
 *
 * @param first_slab_of_caches_base (output value) the virtual address
 * of the slab associated to the slab structure.
 *
 * @param first_slab_of_caches_nb_pages (output value) the number of
 * (virtual) pages used by the first slab of the cache of caches.
 *
 * @param first_struct_slab_of_ranges (output value) the virtual address
 * of the first slab that gets allocated for the cache of ranges. Same
 * explanation as above.
 *
 * @param first_slab_of_ranges_base (output value) the virtual address
 * of the slab associated to the slab structure.
 *
 * @param first_slab_of_ranges_nb_pages (output value) the number of
 * (virtual) pages used by the first slab of the cache of ranges.
 *
 * @return the cache of kmem_range immediatly usable
 */
struct sos_kslab_cache *
sos_kmem_cache_subsystem_setup_prepare(sos_vaddr_t kernel_core_base,
				       sos_vaddr_t kernel_core_top,
				       sos_size_t  sizeof_struct_range,
				       /* results */
				       struct sos_kslab **first_struct_slab_of_caches,
				       sos_vaddr_t *first_slab_of_caches_base,
				       sos_count_t *first_slab_of_caches_nb_pages,
				       struct sos_kslab **first_struct_slab_of_ranges,
				       sos_vaddr_t *first_slab_of_ranges_base,
				       sos_count_t *first_slab_of_ranges_nb_pages);

/**
 * Update the configuration of the cache subsystem once the vmm
 * subsystem has been fully initialized
 */
sos_ret_t
sos_kmem_cache_subsystem_setup_commit(struct sos_kslab *first_struct_slab_of_caches,
				      struct sos_kmem_range *first_range_of_caches,
				      struct sos_kslab *first_struct_slab_of_ranges,
				      struct sos_kmem_range *first_range_of_ranges);


/*
 * Flags for sos_kmem_cache_create()
 */
/** The slabs should be initially mapped in physical memory */
#define SOS_KSLAB_CREATE_MAP  (1<<0)
/** The object should always be set to zero at allocation (implies
    SOS_KSLAB_CREATE_MAP) */
#define SOS_KSLAB_CREATE_ZERO (1<<1)

/**
 * @note this function MAY block (involved allocations are not atomic)
 * @param name must remain valid during the whole cache's life
 *             (shallow copy) !
 * @param cache_flags An or-ed combination of the SOS_KSLAB_CREATE_* flags
 */
struct sos_kslab_cache *
sos_kmem_cache_create(const char* name,
		      sos_size_t  object_size,
		      sos_count_t pages_per_slab,
		      sos_count_t min_free_objects,
		      sos_ui32_t  cache_flags);

sos_ret_t sos_kmem_cache_destroy(struct sos_kslab_cache *kslab_cache);


/*
 * Flags for sos_kmem_cache_alloc()
 */
/** Allocation should either succeed or fail, without blocking */
#define SOS_KSLAB_ALLOC_ATOMIC (1<<0)

/**
 * Allocate an object from the given cache.
 *
 * @param alloc_flags An or-ed combination of the SOS_KSLAB_ALLOC_* flags
 */
sos_vaddr_t sos_kmem_cache_alloc(struct sos_kslab_cache *kslab_cache,
				 sos_ui32_t alloc_flags);


/**
 * Free an object (assumed to be already allocated and not already
 * free) at the given virtual address.
 */
sos_ret_t sos_kmem_cache_free(sos_vaddr_t vaddr);


/*
 * Function reserved to kmem_vmm.c. Does almost everything
 * sos_kmem_cache_free() does, except it does not call
 * sos_kmem_vmm_del_range() if it needs to. This is aimed at avoiding
 * large recursion when a range is freed with
 * sos_kmem_vmm_del_range().
 *
 * @param the_range The range structure to free
 *
 * @return NULL when the range containing 'the_range' still contains
 * other ranges, or the address of the range which owned 'the_range'
 * if it becomes empty.
 */
struct sos_kmem_range *
sos_kmem_cache_release_struct_range(struct sos_kmem_range *the_range);


#endif /* _SOS_KMEM_SLAB_H_ */