L4Re - L4 Runtime Environment
cap_alloc
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /**
3  * \file
4  * \brief Abstract capability-allocator interface
5  */
6 /*
7  * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  * Alexander Warg <warg@os.inf.tu-dresden.de>
9  * economic rights: Technische Universit├Ąt Dresden (Germany)
10  *
11  * This file is part of TUD:OS and distributed under the terms of the
12  * GNU General Public License 2.
13  * Please see the COPYING-GPL-2 file for details.
14  *
15  * As a special exception, you may use this file as part of a free software
16  * library without restriction. Specifically, if other files instantiate
17  * templates or use macros or inline functions from this file, or you compile
18  * this file and link it with other files to produce an executable, this
19  * file does not by itself cause the resulting executable to be covered by
20  * the GNU General Public License. This exception does not however
21  * invalidate any other reasons why the executable file might be covered by
22  * the GNU General Public License.
23  */
24 
25 #pragma once
26 
27 #include <l4/sys/task>
28 #include <l4/sys/smart_capability>
29 #include <l4/re/consts>
30 #include <l4/cxx/type_traits>
31 
32 namespace L4Re {
33 
34 /**
35  * \addtogroup l4re_cap_api
36  */
37 /*@{*/
38 /**
39  * \brief Capability allocator interface.
40  */
41 class Cap_alloc
42 {
43 private:
44  void operator = (Cap_alloc const &);
45 
46 protected:
47  Cap_alloc(Cap_alloc const &) {}
48  Cap_alloc() {}
49 
50 public:
51 
52  /**
53  * \brief Allocate a capability
54  * \return Capability of type void
55  */
56  virtual L4::Cap<void> alloc() throw() = 0;
57  virtual void take(L4::Cap<void> cap) throw() = 0;
58 
59  /**
60  * \brief Allocate a capability
61  * \return Capability of type T
62  */
63  template< typename T >
64  L4::Cap<T> alloc() throw()
65  { return L4::cap_cast<T>(alloc()); }
66 
67  /**
68  * \brief Free a capability
69  * \param cap Capability to free.
70  */
71  virtual void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
72  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() = 0;
73  virtual bool release(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
74  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() = 0;
75 
76  /**
77  * \brief Destructor.
78  */
79  virtual ~Cap_alloc() = 0;
80 
81  /**
82  * \brief Construct an instance of a capability allocator.
83  * \param ca Capability allocator
84  * \return Instance of a capability allocator.
85  */
86  template< typename CAP_ALLOC >
87  static inline L4Re::Cap_alloc *
88  get_cap_alloc(CAP_ALLOC &ca)
89  {
90  struct CA : public L4Re::Cap_alloc
91  {
92  CAP_ALLOC &_ca;
93  L4::Cap<void> alloc() throw() override { return _ca.alloc(); }
94  void take(L4::Cap<void> cap) throw() override { _ca.take(cap); }
95 
96  void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
97  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() override
98  { _ca.free(cap, task, unmap_flags); }
99 
100  bool release(L4::Cap<void> cap, l4_cap_idx_t task,
101  unsigned unmap_flags) throw() override
102  { return _ca.release(cap, task, unmap_flags); }
103 
104  void operator delete(void *) {}
105 
106  CA(CAP_ALLOC &ca) : _ca(ca) {}
107  };
108 
109  static CA _ca(ca);
110  return &_ca;
111  }
112 };
113 
114 template<typename ALLOC>
115 struct Cap_alloc_t : ALLOC, L4Re::Cap_alloc
116 {
117  template<typename ...ARGS>
118  Cap_alloc_t(ARGS &&...args) : ALLOC(cxx::forward<ARGS>(args)...) {}
119 
120  L4::Cap<void> alloc() throw() override { return ALLOC::alloc(); }
121  void take(L4::Cap<void> cap) throw() override { ALLOC::take(cap); }
122 
123  void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
124  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() override
125  { ALLOC::free(cap, task, unmap_flags); }
126 
127  bool release(L4::Cap<void> cap, l4_cap_idx_t task,
128  unsigned unmap_flags) throw() override
129  { return ALLOC::release(cap, task, unmap_flags); }
130 
131  void operator delete(void *) {}
132 };
133 
134 inline
135 Cap_alloc::~Cap_alloc()
136 {}
137 
138 extern Cap_alloc *virt_cap_alloc;
139 
140 /**
141  * \brief Helper for Auto_cap and Auto_del_cap
142  * \ingroup api_l4re_util
143  */
144 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
145 class Smart_cap_auto
146 {
147 private:
148  Cap_alloc *_ca;
149 
150 public:
151  Smart_cap_auto() : _ca(0) {}
152  Smart_cap_auto(Cap_alloc *ca) : _ca(ca) {}
153 
154  void free(L4::Cap_base &c)
155  {
156  if (c.is_valid() && _ca)
157  _ca->free(L4::Cap<void>(c.cap()), This_task, Unmap_flags);
158 
159  invalidate(c);
160  }
161 
162  static void invalidate(L4::Cap_base &c)
163  {
164  if (c.is_valid())
165  c.invalidate();
166  }
167 
168  static L4::Cap_base copy(L4::Cap_base const &src)
169  {
170  L4::Cap_base r = src;
171  invalidate(const_cast<L4::Cap_base &>(src));
172  return r;
173  }
174 };
175 
176 /**
177  * Helper for Ref_cap and Ref_del_cap.
178  */
179 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
180 class Smart_count_cap
181 {
182 private:
183  Cap_alloc *_ca;
184 
185 public:
186  Smart_count_cap() : _ca(nullptr) {}
187  Smart_count_cap(Cap_alloc *ca) : _ca(ca) {}
188  /**
189  * Free operation for L4::Smart_cap
190  * (decrement ref count and delete if 0).
191  */
192  void free(L4::Cap_base &c) throw()
193  {
194  if (c.is_valid())
195  {
196  if (_ca && _ca->release(L4::Cap<void>(c.cap()), This_task, Unmap_flags))
197  c.invalidate();
198  }
199  }
200 
201  /**
202  * Invalidate operation for L4::Smart_cap.
203  */
204  static void invalidate(L4::Cap_base &c) throw()
205  {
206  if (c.is_valid())
207  c.invalidate();
208  }
209 
210  /**
211  * Copy operation for L4::Smart_cap (increment ref count).
212  */
213  L4::Cap_base copy(L4::Cap_base const &src)
214  {
215  if (src.is_valid())
216  _ca->take(L4::Cap<void>(src.cap()));
217  return src;
218  }
219 };
220 
221 /**
222  * \internal the interface is not mature right now
223  * \brief Automatic capability that implements automatic free and
224  * unmap of the capability selector.
225  * \param T the type of the object that is referred by the capability.
226  *
227  * This kind of automatic capability is useful for capabilities
228  * that shall have a lifetime that is strictly coupled to one C++ scope.
229  *
230  * Usage:
231  * \code
232  * {
233  * L4Re::Auto_cap<L4Re::Dataspace>::Cap
234  * ds_cap(L4Re::cap_alloc.alloc<L4Re::Datasapce>));
235  *
236  * // use the dataspace cap
237  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
238  *
239  * ...
240  *
241  * // At the end of the scope ds_cap is unmapped and the capability selector
242  * // is freed.
243  * }
244  * \endcode
245  */
246 template< typename T >
247 struct Auto_cap
248 {
249  typedef L4::Smart_cap<T, Smart_cap_auto<> > Cap;
250 } L4_DEPRECATED("use L4::Re::Unique_cap");
251 
252 /**
253  * \internal the interface is not mature right now
254  * \brief Automatic capability that implements automatic free and
255  * unmap+delete of the capability selector.
256  * \param T the type of the object that is referred by the capability.
257  *
258  * This kind of automatic capability is useful for capabilities
259  * pointing to objects
260  * that shall have a lifetime that is strictly coupled to one C++ scope.
261  * The main difference to Auto_cap is that the unmap is done with the
262  * deletion flag enabled and this leads to the deletion of the object
263  * if the current task holds appropriate deletion rights.
264  *
265  * Usage:
266  * \code
267  * {
268  * L4Re::Auto_del_cap<L4Re::Dataspace>::Cap
269  * ds_cap(L4Re::cap_alloc.alloc<L4Re::Datasapce>));
270  *
271  * // use the dataspace cap
272  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
273  *
274  * ...
275  *
276  * // At the end of the scope ds_cap is unmapped and the capability selector
277  * // is freed. Because the deletion flag is set the data space shall be
278  * // also deleted (even if there are other references to this data space).
279  * }
280  * \endcode
281  */
282 template< typename T >
283 struct Auto_del_cap
284 {
285  typedef L4::Smart_cap<T, Smart_cap_auto<L4_FP_DELETE_OBJ> > Cap;
286 } L4_DEPRECATED("use L4::Re::Unique_del_cap");
287 /*@}*/
288 
289 }