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  * \param task If set, task to unmap the capability from.
71  * \param unmap_flags Flags for unmap, see l4_unmap_flags_t.
72  */
73  virtual void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
74  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() = 0;
75  virtual bool release(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
76  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() = 0;
77 
78  /**
79  * \brief Destructor.
80  */
81  virtual ~Cap_alloc() = 0;
82 
83  /**
84  * \brief Construct an instance of a capability allocator.
85  * \param ca Capability allocator
86  * \return Instance of a capability allocator.
87  */
88  template< typename CAP_ALLOC >
89  static inline L4Re::Cap_alloc *
90  get_cap_alloc(CAP_ALLOC &ca)
91  {
92  struct CA : public L4Re::Cap_alloc
93  {
94  CAP_ALLOC &_ca;
95  L4::Cap<void> alloc() throw() override { return _ca.alloc(); }
96  void take(L4::Cap<void> cap) throw() override { _ca.take(cap); }
97 
98  void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
99  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() override
100  { _ca.free(cap, task, unmap_flags); }
101 
102  bool release(L4::Cap<void> cap, l4_cap_idx_t task,
103  unsigned unmap_flags) throw() override
104  { return _ca.release(cap, task, unmap_flags); }
105 
106  void operator delete(void *) {}
107 
108  CA(CAP_ALLOC &ca) : _ca(ca) {}
109  };
110 
111  static CA _ca(ca);
112  return &_ca;
113  }
114 };
115 
116 template<typename ALLOC>
117 struct Cap_alloc_t : ALLOC, L4Re::Cap_alloc
118 {
119  template<typename ...ARGS>
120  Cap_alloc_t(ARGS &&...args) : ALLOC(cxx::forward<ARGS>(args)...) {}
121 
122  L4::Cap<void> alloc() throw() override { return ALLOC::alloc(); }
123  void take(L4::Cap<void> cap) throw() override { ALLOC::take(cap); }
124 
125  void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
126  unsigned unmap_flags = L4_FP_ALL_SPACES) throw() override
127  { ALLOC::free(cap, task, unmap_flags); }
128 
129  bool release(L4::Cap<void> cap, l4_cap_idx_t task,
130  unsigned unmap_flags) throw() override
131  { return ALLOC::release(cap, task, unmap_flags); }
132 
133  void operator delete(void *) {}
134 };
135 
136 inline
137 Cap_alloc::~Cap_alloc()
138 {}
139 
140 extern Cap_alloc *virt_cap_alloc;
141 
142 /**
143  * \brief Helper for Auto_cap and Auto_del_cap
144  * \ingroup api_l4re_util
145  */
146 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
147 class Smart_cap_auto
148 {
149 private:
150  Cap_alloc *_ca;
151 
152 public:
153  Smart_cap_auto() : _ca(0) {}
154  Smart_cap_auto(Cap_alloc *ca) : _ca(ca) {}
155 
156  void free(L4::Cap_base &c)
157  {
158  if (c.is_valid() && _ca)
159  _ca->free(L4::Cap<void>(c.cap()), This_task, Unmap_flags);
160 
161  invalidate(c);
162  }
163 
164  static void invalidate(L4::Cap_base &c)
165  {
166  if (c.is_valid())
167  c.invalidate();
168  }
169 
170  static L4::Cap_base copy(L4::Cap_base const &src)
171  {
172  L4::Cap_base r = src;
173  invalidate(const_cast<L4::Cap_base &>(src));
174  return r;
175  }
176 };
177 
178 /**
179  * Helper for Ref_cap and Ref_del_cap.
180  */
181 template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
182 class Smart_count_cap
183 {
184 private:
185  Cap_alloc *_ca;
186 
187 public:
188  Smart_count_cap() : _ca(nullptr) {}
189  Smart_count_cap(Cap_alloc *ca) : _ca(ca) {}
190  /**
191  * Free operation for L4::Smart_cap
192  * (decrement ref count and delete if 0).
193  */
194  void free(L4::Cap_base &c) throw()
195  {
196  if (c.is_valid())
197  {
198  if (_ca && _ca->release(L4::Cap<void>(c.cap()), This_task, Unmap_flags))
199  c.invalidate();
200  }
201  }
202 
203  /**
204  * Invalidate operation for L4::Smart_cap.
205  */
206  static void invalidate(L4::Cap_base &c) throw()
207  {
208  if (c.is_valid())
209  c.invalidate();
210  }
211 
212  /**
213  * Copy operation for L4::Smart_cap (increment ref count).
214  */
215  L4::Cap_base copy(L4::Cap_base const &src)
216  {
217  if (src.is_valid())
218  _ca->take(L4::Cap<void>(src.cap()));
219  return src;
220  }
221 };
222 
223 /**
224  * \internal the interface is not mature right now
225  * \brief Automatic capability that implements automatic free and
226  * unmap of the capability selector.
227  * \param T the type of the object that is referred by the capability.
228  *
229  * This kind of automatic capability is useful for capabilities
230  * that shall have a lifetime that is strictly coupled to one C++ scope.
231  *
232  * Usage:
233  * \code
234  * {
235  * L4Re::Auto_cap<L4Re::Dataspace>::Cap
236  * ds_cap(L4Re::cap_alloc.alloc<L4Re::Datasapce>));
237  *
238  * // use the dataspace cap
239  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
240  *
241  * ...
242  *
243  * // At the end of the scope ds_cap is unmapped and the capability selector
244  * // is freed.
245  * }
246  * \endcode
247  */
248 template< typename T >
249 struct Auto_cap
250 {
251  typedef L4::Smart_cap<T, Smart_cap_auto<> > Cap;
252 } L4_DEPRECATED("use L4::Re::Unique_cap");
253 
254 /**
255  * \internal the interface is not mature right now
256  * \brief Automatic capability that implements automatic free and
257  * unmap+delete of the capability selector.
258  * \param T the type of the object that is referred by the capability.
259  *
260  * This kind of automatic capability is useful for capabilities
261  * pointing to objects
262  * that shall have a lifetime that is strictly coupled to one C++ scope.
263  * The main difference to Auto_cap is that the unmap is done with the
264  * deletion flag enabled and this leads to the deletion of the object
265  * if the current task holds appropriate deletion rights.
266  *
267  * Usage:
268  * \code
269  * {
270  * L4Re::Auto_del_cap<L4Re::Dataspace>::Cap
271  * ds_cap(L4Re::cap_alloc.alloc<L4Re::Datasapce>));
272  *
273  * // use the dataspace cap
274  * L4Re::chksys(mem_alloc->alloc(4096, ds_cap.get()));
275  *
276  * ...
277  *
278  * // At the end of the scope ds_cap is unmapped and the capability selector
279  * // is freed. Because the deletion flag is set the data space shall be
280  * // also deleted (even if there are other references to this data space).
281  * }
282  * \endcode
283  */
284 template< typename T >
285 struct Auto_del_cap
286 {
287  typedef L4::Smart_cap<T, Smart_cap_auto<L4_FP_DELETE_OBJ> > Cap;
288 } L4_DEPRECATED("use L4::Re::Unique_del_cap");
289 /*@}*/
290 
291 }