L4Re - L4 Runtime Environment
cap_alloc
Go to the documentation of this file.
1 // -*- Mode: C++ -*-
2 // vim:ft=cpp
3 /**
4  * \file
5  * Capability allocator
6  */
7 /*
8  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9  * Alexander Warg <warg@os.inf.tu-dresden.de>
10  * economic rights: Technische Universit├Ąt Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction. Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License. This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25 
26 #pragma once
27 
28 #include <l4/re/util/cap_alloc_impl.h>
29 #include <l4/sys/smart_capability>
30 #include <l4/sys/task>
31 #include <l4/re/consts>
32 
33 namespace L4Re { namespace Util {
34 
35 /**
36  * \defgroup l4re_cap_api L4Re Capability API
37  * \ingroup api_l4re_util
38  */
39 /*@{*/
40 /**
41  * Capability allocator.
42  *
43  * This is the instance of the capability allocator that is used
44  * by usual applications. The actual implementation of the allocator
45  * depends on the configuration of the system.
46  *
47  * Per default we use Counting_cap_alloc, a reference-counting
48  * capability allocator, that
49  * keeps a reference counter for each managed capability selector.
50  *
51  * \note This capability allocator is not thread-safe.
52  */
53 extern _Cap_alloc &cap_alloc;
54 
55 /**
56  * Helper for Auto_cap and Auto_del_cap.
57  */
58 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
59 class Smart_cap_auto
60 {
61 public:
62  /**
63  * Free operation for L4::Smart_cap.
64  */
65  static void free(L4::Cap_base &c)
66  {
67  if (c.is_valid())
68  {
69  cap_alloc.free(L4::Cap<void>(c.cap()), This_task, Unmap_flags);
70  c.invalidate();
71  }
72  }
73 
74  /**
75  * Invalidate operation for L4::Smart_cap.
76  */
77  static void invalidate(L4::Cap_base &c)
78  {
79  if (c.is_valid())
80  c.invalidate();
81  }
82 
83  /**
84  * Copy operation for L4::Smart_cap.
85  */
86  static L4::Cap_base copy(L4::Cap_base const &src)
87  {
88  L4::Cap_base r = src;
89  invalidate(const_cast<L4::Cap_base &>(src));
90  return r;
91  }
92 };
93 
94 
95 /**
96  * Helper for Ref_cap and Ref_del_cap.
97  */
98 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
99 class Smart_count_cap
100 {
101 public:
102  /**
103  * Free operation for L4::Smart_cap
104  * (decrement ref count and delete if 0).
105  */
106  static void free(L4::Cap_base &c) throw()
107  {
108  if (c.is_valid())
109  {
110  if (cap_alloc.release(L4::Cap<void>(c.cap()), This_task, Unmap_flags))
111  c.invalidate();
112  }
113  }
114 
115  /**
116  * Invalidate operation for L4::Smart_cap.
117  */
118  static void invalidate(L4::Cap_base &c) throw()
119  {
120  if (c.is_valid())
121  c.invalidate();
122  }
123 
124  /**
125  * Copy operation for L4::Smart_cap (increment ref count).
126  */
127  static L4::Cap_base copy(L4::Cap_base const &src)
128  {
129  cap_alloc.take(L4::Cap<void>(src.cap()));
130  return src;
131  }
132 };
133 
134 
135 /**
136  * Automatic capability that implements automatic free and
137  * unmap of the capability selector.
138  *
139  * \tparam T Type of the object that is referred by the capability.
140  *
141  * \deprecated Use L4Re::Util::Unique_cap.
142  *
143  * This kind of automatic capability is useful for capabilities that
144  * shall have a lifetime that is strictly coupled to one C++ scope.
145  *
146  * Usage:
147  * ~~~
148  * {
149  * L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap
150  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
151  *
152  * // use the dataspace cap
153  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
154  *
155  * ...
156  *
157  * // At the end of the scope ds_cap is unmapped and the capability selector
158  * // is freed.
159  * }
160  * ~~~
161  */
162 template< typename T >
163 struct Auto_cap
164 {
165  typedef L4::Smart_cap<T, Smart_cap_auto< L4_FP_ALL_SPACES> > Cap;
166 } L4_DEPRECATED("use L4Re::Util::Unique_cap");
167 
168 /**
169  * Automatic capability that implements automatic free and
170  * unmap+delete of the capability selector.
171  *
172  * \tparam T Type of the object that is referred by the capability.
173  *
174  * \deprecated Use L4Re::Util::Unique_cap.
175  *
176  * This kind of automatic capability is useful for capabilities with
177  * that shall have a lifetime that is strictly coupled to one C++ scope.
178  * The main difference to Auto_cap is that the unmap is done with the
179  * deletion flag enabled and this leads to the deletion of the object
180  * if the current task holds appropriate deletion rights.
181  *
182  * Usage:
183  * ~~~
184  * {
185  * L4Re::Util::Auto_del_cap<L4Re::Dataspace>::Cap
186  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
187  *
188  * // use the dataspace cap
189  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
190  *
191  * ...
192  *
193  * // At the end of the scope ds_cap is unmapped and the capability selector
194  * // is freed. Because the deletion flag is set the data space shall be
195  * // also deleted (even if there are other references to this data space).
196  * }
197  * ~~~
198  */
199 template< typename T >
200 struct Auto_del_cap
201 {
202  typedef L4::Smart_cap<T, Smart_cap_auto<L4_FP_DELETE_OBJ> > Cap;
203 } L4_DEPRECATED("use L4Re::Util::Unique_cap");
204 
205 /**
206  * Automatic capability that implements automatic free and
207  * unmap of the capability selector.
208  *
209  * \tparam T Type of the object that is referred by the capability.
210  *
211  * This kind of automatic capability implements a counted reference to a
212  * capability selector. The capability shall be unmapped and freed
213  * when the reference count in the allocator goes to zero.
214  *
215  * Usage:
216  * ~~~
217  * L4Re::Util::Ref_cap<L4Re::Dataspace>::Cap global_ds_cap;
218  *
219  * {
220  * L4Re::Util::Ref_cap<L4Re::Dataspace>::Cap
221  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
222  * // reference count for the allocated cap selector is now 1
223  *
224  * // use the dataspace cap
225  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
226  *
227  * global_ds_cap = ds_cap;
228  * // reference count is now 2
229  * ...
230  * }
231  * // reference count dropped to 1 (ds_cap is no longer existing).
232  * ~~~
233  */
234 template< typename T >
235 struct Ref_cap
236 {
237  typedef L4::Smart_cap<T, Smart_count_cap<L4_FP_ALL_SPACES> > Cap;
238 };
239 
240 /**
241  * Automatic capability that implements automatic free and
242  * unmap+delete of the capability selector.
243  *
244  * \tparam T Type of the object that is referred by the capability.
245  *
246  * This kind of automatic capability implements a counted reference to a
247  * capability selector. The capability shall be unmapped and freed
248  * when the reference count in the allocator goes to zero.
249  * The main difference to Ref_cap is that the unmap is done with the
250  * deletion flag enabled and this leads to the deletion of the object
251  * if the current task holds appropriate deletion rights.
252  *
253  * Usage:
254  * ~~~
255  * L4Re::Util::Ref_del_cap<L4Re::Dataspace>::Cap global_ds_cap;
256  *
257  * {
258  * L4Re::Util::Ref_del_cap<L4Re::Dataspace>::Cap
259  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
260  * // reference count for the allocated cap selector is now 1
261  *
262  * // use the dataspace cap
263  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
264  *
265  * global_ds_cap = ds_cap;
266  * // reference count is now 2
267  * ...
268  * }
269  * // reference count dropped to 1 (ds_cap is no longer existing).
270  * ...
271  * global_ds_cap = L4_INVALID_CAP;
272  * // reference count dropped to 0 (data space shall be deleted).
273  * ~~~
274  */
275 template< typename T >
276 struct Ref_del_cap
277 {
278  typedef L4::Smart_cap<T, Smart_count_cap<L4_FP_DELETE_OBJ> > Cap;
279 };
280 
281 /**
282  * Allocate a capability slot and wrap it in an Auto_cap.
283  *
284  * \tparam T Type of capability the slot is used for.
285  *
286  * \deprecated Use L4Re::Util::make_unique_cap().
287  */
288 #pragma GCC diagnostic push
289 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
290 template< typename T >
291 typename Auto_cap<T>::Cap
292 L4_DEPRECATED("use make_unique_cap")
293 make_auto_cap()
294 { return typename Auto_cap<T>::Cap(cap_alloc.alloc<T>()); }
295 
296 /**
297  * Allocate a capability slot and wrap it in an Auto_del_cap.
298  *
299  * \tparam T Type of capability the slot is used for.
300  *
301  * \deprecated Use L4Re::Util::make_unique_del_cap().
302  */
303 template< typename T >
304 typename Auto_del_cap<T>::Cap
305 make_auto_del_cap()
306 { return typename Auto_del_cap<T>::Cap(cap_alloc.alloc<T>()); }
307 #pragma GCC diagnostic pop
308 
309 /**
310  * Allocate a capability slot and wrap it in a Ref_cap.
311  *
312  * \tparam T Type of capability the slot is used for.
313  */
314 template< typename T >
315 typename Ref_cap<T>::Cap
316 make_ref_cap() { return typename Ref_cap<T>::Cap(cap_alloc.alloc<T>()); }
317 
318 /**
319  * Allocate a capability slot and wrap it in a Ref_del_cap.
320  *
321  * \tparam T Type of capability the slot is used for.
322  */
323 template< typename T >
324 typename Ref_del_cap<T>::Cap
325 make_ref_del_cap()
326 { return typename Ref_del_cap<T>::Cap(cap_alloc.alloc<T>()); }
327 
328 /*@}*/
329 
330 }}
331