3 * (c) 2008-2009 Technische Universität Dresden
4 * This file is part of TUD:OS and distributed under the terms of the
5 * GNU General Public License 2.
6 * Please see the COPYING-GPL-2 file for details.
8 * As a special exception, you may use this file as part of a free software
9 * library without restriction. Specifically, if other files instantiate
10 * templates or use macros or inline functions from this file, or you compile
11 * this file and link it with other files to produce an executable, this
12 * file does not by itself cause the resulting executable to be covered by
13 * the GNU General Public License. This exception does not however
14 * invalidate any other reasons why the executable file might be covered by
15 * the GNU General Public License.
20 #include <l4/cxx/std_alloc>
21 #include <l4/cxx/list>
22 #include <l4/sys/consts.h>
28 * \brief Basic slab allocator.
29 * \param Obj_size The size of the objects managed by the allocator (in bytes).
30 * \param Slab_size The size of a slab cache (in bytes).
31 * \param Max_free The maximum number of free slab caches. When this limit is
32 * reached slab caches are freed.
33 * \param Alloc The allocator that is used to allocate the slab caches.
35 template< int Obj_size, int Slab_size = L4_PAGESIZE,
36 int Max_free = 2, template<typename A> class Alloc = New_allocator >
49 struct Slab_head : public List_item
53 Base_slab<Obj_size, Slab_size, Max_free, Alloc> *cache;
55 inline Slab_head() throw() : num_free(0), free(0), cache(0)
62 object_size = Obj_size, ///< size of an object.
63 slab_size = Slab_size, ///< size of a slab cache.
64 /// objects per slab cache.
65 objects_per_slab = (Slab_size - sizeof(Slab_head)) / object_size,
66 /// maximum number of free slab caches.
67 max_free_slabs = Max_free,
73 char _o[slab_size - sizeof(Slab_head)];
74 Free_o *object(unsigned obj) throw()
75 { return reinterpret_cast<Free_o*>(_o + object_size * obj); }
78 struct Slab_i : public Slab_store, public Slab_head
82 /// Type of the allocator for the slab caches.
83 typedef Alloc<Slab_i> Slab_alloc;
85 typedef void Obj_type;
92 Slab_i *_partial_slabs;
95 /// Add a new slab cache.
96 void add_slab(Slab_i *s) throw()
98 s->num_free = objects_per_slab;
101 //L4::cerr << "Slab: " << this << "->add_slab(" << s << ", size="
102 // << slab_size << "):" << " f=" << s->object(0) << '\n';
104 // initialize free list
105 Free_o *f = s->free = s->object(0);
106 for (unsigned i = 0; i < objects_per_slab; ++i)
108 f->next = s->object(i);
113 // insert slab into cache's list
114 _empty_slabs = List_item::push_front(_empty_slabs, s);
119 /// Grow the allocator, by adding a new slab cache.
122 Slab_i *s = _alloc.alloc();
126 new (s, cxx::Nothrow()) Slab_i();
132 /// Shrink the allocator by freeing free slab caches.
133 void shrink() throw()
135 if (!_alloc.can_free)
138 while (_empty_slabs && _num_free > max_free_slabs)
140 Slab_i *s = _empty_slabs;
141 _empty_slabs = List_item::remove(_empty_slabs, s);
149 Base_slab(Slab_alloc const &alloc = Slab_alloc()) throw()
150 : _alloc(alloc), _num_free(0), _num_slabs(0), _full_slabs(0),
151 _partial_slabs(0), _empty_slabs(0)
158 Slab_i *o = _empty_slabs;
159 _empty_slabs = List_item::remove(_empty_slabs, o);
162 while (_partial_slabs)
164 Slab_i *o = _partial_slabs;
165 _partial_slabs = List_item::remove(_partial_slabs, o);
170 Slab_i *o = _full_slabs;
171 _full_slabs = List_item::remove(_full_slabs, o);
176 void *alloc() throw()
178 Slab_i **free = &_partial_slabs;
180 free = &_empty_slabs;
182 if (!(*free) && !grow())
189 if (free == &_empty_slabs)
191 _empty_slabs = List_item::remove(_empty_slabs, s);
199 _partial_slabs = List_item::remove(_partial_slabs, s);
200 _full_slabs = List_item::push_front(_full_slabs, s);
202 else if (free == &_empty_slabs)
203 _partial_slabs = List_item::push_front(_partial_slabs, s);
205 //L4::cerr << this << "->alloc(): " << o << ", of " << s << '\n';
210 void free(void *_o) throw()
215 unsigned long addr = (unsigned long)_o;
216 addr = (addr / slab_size) * slab_size;
217 Slab_i *s = (Slab_i*)addr;
219 if (s->cache != this)
222 Free_o *o = reinterpret_cast<Free_o*>(_o);
227 bool was_full = false;
231 _full_slabs = List_item::remove(_full_slabs, s);
237 if (s->num_free == objects_per_slab)
240 _partial_slabs = List_item::remove(_partial_slabs, s);
242 _empty_slabs = List_item::push_front(_empty_slabs, s);
244 if (_num_free > max_free_slabs)
251 _partial_slabs = List_item::push_front(_partial_slabs, s);
253 //L4::cerr << this << "->free(" << _o << "): of " << s << '\n';
257 * \brief Get the total number of objects managed by the slab allocator.
258 * \return The number of objects managed by the allocator (including the
261 unsigned total_objects() const throw()
262 { return _num_slabs * objects_per_slab; }
265 * \brief Get the total number of objects managed by the slab allocator.
266 * \return The number of objects managed by the allocator (including the
269 unsigned free_objects() const throw()
273 /* count partial slabs first */
274 List_item::T_iter<Slab_i> s = _partial_slabs;
277 count += s->num_free;
281 /* add empty slabs */
282 count += _num_free * objects_per_slab;
290 * \brief Slab allocator for object of type \a Type.
291 * \param Type the type of the objects to manage.
292 * \param Slab_size size of a slab cache.
293 * \param Max_free the maximum number of free slab caches.
294 * \param Alloc the allocator for the slab caches.
296 template<typename Type, int Slab_size = L4_PAGESIZE,
297 int Max_free = 2, template<typename A> class Alloc = New_allocator >
298 class Slab : public Base_slab<sizeof(Type), Slab_size, Max_free, Alloc>
301 typedef Base_slab<sizeof(Type), Slab_size, Max_free, Alloc> Base_type;
304 typedef Type Obj_type;
306 Slab(typename Base_type::Slab_alloc const &alloc
307 = typename Base_type::Slab_alloc()) throw()
308 : Base_slab<sizeof(Type), Slab_size, Max_free, Alloc>(alloc) {}
312 * \brief Allocate an object of type \a Type.
313 * \return A pointer to the object just allocated, or 0 on failure.
315 Type *alloc() throw()
317 return (Type*)Base_slab<sizeof(Type), Slab_size,
318 Max_free, Alloc>::alloc();
322 * \brief Free the object addressed by \a o.
323 * \param o The pointer to the object to free.
324 * \pre The object must have been allocated with this allocator.
326 void free(Type *o) throw()
327 { Base_slab<sizeof(Type), Slab_size, Max_free, Alloc>::free(o); }
333 * \brief Merged slab allocator (allocators for objects of the same size
334 * are merged together).
336 * \param Obj_size The size of an object managed by the slab allocator.
337 * \param Slab_size The size of a slab cache.
338 * \param Max_free The maximum number of free slab caches.
339 * \param Alloc The allocator for the slab caches.
341 * This slab allocator class is useful for merging slab allocators with the
342 * same parameters (equal \a Obj_size, \a Slab_size, \a Max_free, and
343 * \a Alloc parameters) together and share the overhead for the slab caches
344 * among all equal-sized objects.
347 template< int Obj_size, int Slab_size = L4_PAGESIZE,
348 int Max_free = 2, template<typename A> class Alloc = New_allocator >
349 class Base_slab_static
352 typedef Base_slab<Obj_size, Slab_size, Max_free, Alloc> _A;
355 typedef void Obj_type;
358 object_size = Obj_size, ///< size of an object.
359 slab_size = Slab_size, ///< size of a slab cache.
360 /// number of objects per slab cache.
361 objects_per_slab = _A::objects_per_slab,
362 max_free_slabs = Max_free, ///< maximum number of free slab caches.
365 /** \brief Allocate an object. */
366 void *alloc() throw() { return _a.alloc(); }
368 * \brief Free the given object (\a p).
369 * \param p The pointer to the object to free.
370 * \pre \a p must be a pointer to an object allocated by this allocator.
372 void free(void *p) throw() { _a.free(p); }
375 * \brief Get the total number of objects managed by the slab allocator.
376 * \return The number of objects managed by the allocator (including the
378 * \note The value is the merged value for all equal parameterized
379 * Base_slab_static instances.
381 unsigned total_objects() const throw() { return _a.total_objects(); }
384 * \brief Get the number of free objects in the slab allocator.
385 * \return The number of free objects in all free and partially used
386 * slab caches managed by this allocator.
387 * \note The value is the merged value for all equal parameterized
388 * Base_slab_static instances.
390 unsigned free_objects() const throw() { return _a.free_objects(); }
394 template< int _O, int _S, int _M, template<typename A> class Alloc >
395 typename Base_slab_static<_O,_S,_M,Alloc>::_A
396 Base_slab_static<_O,_S,_M,Alloc>::_a;
400 * \brief Merged slab allocator (allocators for objects of the same size
401 * are merged together).
403 * \param Type The type of the objects to manage.
404 * \param Slab_size The size of a slab cache.
405 * \param Max_free The maximum number of free slab caches.
406 * \param Alloc The allocator for the slab caches.
408 * This slab allocator class is useful for merging slab allocators with the
409 * same parameters (equal \a sizeof(Type), \a Slab_size, \a Max_free, and
410 * \a Alloc parameters) together and share the overhead for the slab caches
411 * among all equal-sized objects.
414 template<typename Type, int Slab_size = L4_PAGESIZE,
415 int Max_free = 2, template<typename A> class Alloc = New_allocator >
417 : public Base_slab_static<sizeof(Type), Slab_size, Max_free, Alloc>
421 typedef Type Obj_type;
423 * \brief Allocate an object of type \a Type.
424 * \return A pointer to the just allocated object, or 0 of failure.
426 Type *alloc() throw()
428 return (Type*)Base_slab_static<sizeof(Type), Slab_size,
429 Max_free, Alloc>::alloc();