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 32namespace L4Re { 33 34/** 35 * \addtogroup l4re_cap_api 36 */ 37/*@{*/ 38/** 39 * \brief Capability allocator interface. 40 */ 41class Cap_alloc 42{ 43private: 44 void operator = (Cap_alloc const &); 45 46protected: 47 Cap_alloc(Cap_alloc const &) {} 48 Cap_alloc() {} 49 50public: 51 52 /** 53 * \brief Allocate a capability 54 * \return Capability of type void 55 */ 56 virtual L4::Cap<void> alloc() noexcept = 0; 57 virtual void take(L4::Cap<void> cap) noexcept = 0; 58 59 /** 60 * \brief Allocate a capability 61 * \return Capability of type T 62 */ 63 template< typename T > 64 L4::Cap<T> alloc() noexcept 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) noexcept = 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) noexcept = 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() noexcept override { return _ca.alloc(); } 96 void take(L4::Cap<void> cap) noexcept 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) noexcept 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) noexcept 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 116template<typename ALLOC> 117struct 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() noexcept override { return ALLOC::alloc(); } 123 void take(L4::Cap<void> cap) noexcept 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) noexcept 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) noexcept override 131 { return ALLOC::release(cap, task, unmap_flags); } 132 133 void operator delete(void *) {} 134}; 135 136inline 137Cap_alloc::~Cap_alloc() 138{} 139 140extern Cap_alloc *virt_cap_alloc; 141 142/** 143 * \brief Helper for Unique_cap and Unique_del_cap 144 * \ingroup api_l4re_util 145 */ 146template< unsigned long Unmap_flags = L4_FP_ALL_SPACES > 147class Smart_cap_auto 148{ 149private: 150 Cap_alloc *_ca; 151 152public: 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 */ 181template< unsigned long Unmap_flags = L4_FP_ALL_SPACES > 182class Smart_count_cap 183{ 184private: 185 Cap_alloc *_ca; 186 187public: 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) noexcept 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) noexcept 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} 225