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  * This kind of automatic capability is useful for capabilities that
142  * shall have a lifetime that is strictly coupled to one C++ scope.
143  *
144  * Usage:
145  * ~~~
146  * {
147  * L4Re::Util::Auto_cap<L4Re::Dataspace>::Cap
148  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
149  *
150  * // use the dataspace cap
151  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
152  *
153  * ...
154  *
155  * // At the end of the scope ds_cap is unmapped and the capability selector
156  * // is freed.
157  * }
158  * ~~~
159  */
160 template< typename T >
161 struct Auto_cap
162 {
163  typedef L4::Smart_cap<T, Smart_cap_auto< L4_FP_ALL_SPACES> > Cap;
164 } L4_DEPRECATED("use L4::Re::Util::Unique_cap");
165 
166 /**
167  * Automatic capability that implements automatic free and
168  * unmap+delete of the capability selector.
169  *
170  * \tparam T Type of the object that is referred by the capability.
171  *
172  * This kind of automatic capability is useful for capabilities with
173  * that shall have a lifetime that is strictly coupled to one C++ scope.
174  * The main difference to Auto_cap is that the unmap is done with the
175  * deletion flag enabled and this leads to the deletion of the object
176  * if the current task holds appropriate deletion rights.
177  *
178  * Usage:
179  * ~~~
180  * {
181  * L4Re::Util::Auto_del_cap<L4Re::Dataspace>::Cap
182  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
183  *
184  * // use the dataspace cap
185  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
186  *
187  * ...
188  *
189  * // At the end of the scope ds_cap is unmapped and the capability selector
190  * // is freed. Because the deletion flag is set the data space shall be
191  * // also deleted (even if there are other references to this data space).
192  * }
193  * ~~~
194  */
195 template< typename T >
196 struct Auto_del_cap
197 {
198  typedef L4::Smart_cap<T, Smart_cap_auto<L4_FP_DELETE_OBJ> > Cap;
199 } L4_DEPRECATED("use L4::Re::Util::Unique_cap");
200 
201 /**
202  * Automatic capability that implements automatic free and
203  * unmap of the capability selector.
204  *
205  * \tparam T Type of the object that is referred by the capability.
206  *
207  * This kind of automatic capability implements a counted reference to a
208  * capability selector. The capability shall be unmapped and freed
209  * when the reference count in the allocator goes to zero.
210  *
211  * Usage:
212  * ~~~
213  * L4Re::Util::Ref_cap<L4Re::Dataspace>::Cap global_ds_cap;
214  *
215  * {
216  * L4Re::Util::Ref_cap<L4Re::Dataspace>::Cap
217  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
218  * // reference count for the allocated cap selector is now 1
219  *
220  * // use the dataspace cap
221  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
222  *
223  * global_ds_cap = ds_cap;
224  * // reference count is now 2
225  * ...
226  * }
227  * // reference count dropped to 1 (ds_cap is no longer existing).
228  * ~~~
229  */
230 template< typename T >
231 struct Ref_cap
232 {
233  typedef L4::Smart_cap<T, Smart_count_cap<L4_FP_ALL_SPACES> > Cap;
234 };
235 
236 /**
237  * Automatic capability that implements automatic free and
238  * unmap+delete of the capability selector.
239  *
240  * \tparam T Type of the object that is referred by the capability.
241  *
242  * This kind of automatic capability implements a counted reference to a
243  * capability selector. The capability shall be unmapped and freed
244  * when the reference count in the allocator goes to zero.
245  * The main difference to Ref_cap is that the unmap is done with the
246  * deletion flag enabled and this leads to the deletion of the object
247  * if the current task holds appropriate deletion rights.
248  *
249  * Usage:
250  * ~~~
251  * L4Re::Util::Ref_del_cap<L4Re::Dataspace>::Cap global_ds_cap;
252  *
253  * {
254  * L4Re::Util::Ref_del_cap<L4Re::Dataspace>::Cap
255  * ds_cap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
256  * // reference count for the allocated cap selector is now 1
257  *
258  * // use the dataspace cap
259  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
260  *
261  * global_ds_cap = ds_cap;
262  * // reference count is now 2
263  * ...
264  * }
265  * // reference count dropped to 1 (ds_cap is no longer existing).
266  * ...
267  * global_ds_cap = L4_INVALID_CAP;
268  * // reference count dropped to 0 (data space shall be deleted).
269  * ~~~
270  */
271 template< typename T >
272 struct Ref_del_cap
273 {
274  typedef L4::Smart_cap<T, Smart_count_cap<L4_FP_DELETE_OBJ> > Cap;
275 };
276 
277 /**
278  * Allocate a capability slot and wrap it in an Auto_cap.
279  *
280  * \tparam T Type of capability the slot is used for.
281  */
282 #pragma GCC diagnostic push
283 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
284 template< typename T >
285 typename Auto_cap<T>::Cap
286 L4_DEPRECATED("use make_unique_cap")
287 make_auto_cap()
288 { return typename Auto_cap<T>::Cap(cap_alloc.alloc<T>()); }
289 
290 /**
291  * Allocate a capability slot and wrap it in an Auto_del_cap.
292  *
293  * \tparam T Type of capability the slot is used for.
294  */
295 template< typename T >
296 typename Auto_del_cap<T>::Cap
297 make_auto_del_cap()
298 { return typename Auto_del_cap<T>::Cap(cap_alloc.alloc<T>()); }
299 #pragma GCC diagnostic pop
300 
301 /**
302  * Allocate a capability slot and wrap it in a Ref_cap.
303  *
304  * \tparam T Type of capability the slot is used for.
305  */
306 template< typename T >
307 typename Ref_cap<T>::Cap
308 make_ref_cap() { return typename Ref_cap<T>::Cap(cap_alloc.alloc<T>()); }
309 
310 /**
311  * Allocate a capability slot and wrap it in a Ref_del_cap.
312  *
313  * \tparam T Type of capability the slot is used for.
314  */
315 template< typename T >
316 typename Ref_del_cap<T>::Cap
317 make_ref_del_cap()
318 { return typename Ref_del_cap<T>::Cap(cap_alloc.alloc<T>()); }
319 
320 /*@}*/
321 
322 }}
323