5 * \brief Reference-counting capability allocator
8 * (c) 2008-2010 Technische Universität Dresden
9 * This file is part of TUD:OS and distributed under the terms of the
10 * GNU General Public License 2.
11 * Please see the COPYING-GPL-2 file for details.
13 * As a special exception, you may use this file as part of a free software
14 * library without restriction. Specifically, if other files instantiate
15 * templates or use macros or inline functions from this file, or you compile
16 * this file and link it with other files to produce an executable, this
17 * file does not by itself cause the resulting executable to be covered by
18 * the GNU General Public License. This exception does not however
19 * invalidate any other reasons why the executable file might be covered by
20 * the GNU General Public License.
25 #include <l4/sys/task>
26 #include <l4/re/consts>
28 namespace L4Re { namespace Util {
30 template< typename COUNTER = unsigned char >
36 static Type nil() { return 0; }
38 void free() { _cnt = 0; }
39 bool is_free() const { return _cnt == 0; }
40 void inc() { ++_cnt; }
41 Type dec() { return --_cnt; }
42 void alloc() { _cnt = 1; }
46 * \brief Reference-counting cap allocator
47 * \ingroup api_l4re_util
49 template <typename COUNTERTYPE = L4Re::Util::Counter<unsigned char> >
50 class Counting_cap_alloc
53 void operator = (Counting_cap_alloc const &) { }
54 typedef COUNTERTYPE Counter;
64 template <unsigned COUNT>
65 struct Counter_storage
67 COUNTERTYPE _buf[COUNT];
68 typedef COUNTERTYPE Buf_type[COUNT];
69 enum { Size = COUNT };
74 Counting_cap_alloc() throw()
75 : _items(0), _free_hint(0), _bias(0), _capacity(0)
78 void setup(void *m, long capacity, long bias) throw()
86 L4::Cap<void> alloc() throw()
88 if (_free_hint >= _capacity)
89 return L4::Cap_base::Invalid;
91 for (long i = _free_hint; i < _capacity; ++i)
93 if (_items[i].is_free())
98 return L4::Cap<void>((i + _bias) << L4_CAP_SHIFT);
102 return L4::Cap<void>::Invalid;
105 template <typename T>
106 L4::Cap<T> alloc() throw()
108 return L4::cap_cast<T>(alloc());
112 void take(L4::Cap<void> cap) throw()
114 long c = cap.cap() >> L4_CAP_SHIFT;
126 bool free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
127 unsigned unmap_flags = L4_FP_ALL_SPACES) throw()
129 long c = cap.cap() >> L4_CAP_SHIFT;
138 if (task != L4_INVALID_CAP)
139 l4_task_unmap(task, cap.fpage(), unmap_flags);
146 bool release(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
147 unsigned unmap_flags = L4_FP_ALL_SPACES) throw()
149 long c = cap.cap() >> L4_CAP_SHIFT;
158 if (_items[c].dec() == Counter::nil())
160 if (task != L4_INVALID_CAP)
161 l4_task_unmap(task, cap.fpage(), unmap_flags);
171 return _capacity + _bias - 1;