182 lines
3.9 KiB
C++
182 lines
3.9 KiB
C++
// vi:set ft=cpp: -*- Mode: C++ -*-
|
|
/**
|
|
* \file
|
|
* \brief Abstract capability-allocator interface
|
|
*/
|
|
/*
|
|
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
|
|
* Alexander Warg <warg@os.inf.tu-dresden.de>
|
|
* economic rights: Technische Universität Dresden (Germany)
|
|
*
|
|
* License: see LICENSE.spdx (in this directory or the directories above)
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <l4/sys/task>
|
|
#include <l4/sys/smart_capability>
|
|
#include <l4/re/consts>
|
|
#include <l4/cxx/type_traits>
|
|
|
|
namespace L4Re {
|
|
|
|
/**
|
|
* \addtogroup l4re_cap_api
|
|
*/
|
|
/**@{*/
|
|
/**
|
|
* \brief Capability allocator interface.
|
|
*/
|
|
class Cap_alloc
|
|
{
|
|
private:
|
|
void operator = (Cap_alloc const &);
|
|
|
|
protected:
|
|
Cap_alloc(Cap_alloc const &) {}
|
|
Cap_alloc() {}
|
|
|
|
public:
|
|
|
|
/**
|
|
* \brief Allocate a capability
|
|
* \return Capability of type void
|
|
*/
|
|
virtual L4::Cap<void> alloc() noexcept = 0;
|
|
virtual void take(L4::Cap<void> cap) noexcept = 0;
|
|
|
|
/**
|
|
* \brief Allocate a capability
|
|
* \return Capability of type T
|
|
*/
|
|
template< typename T >
|
|
L4::Cap<T> alloc() noexcept
|
|
{ return L4::cap_cast<T>(alloc()); }
|
|
|
|
/**
|
|
* \brief Free a capability
|
|
* \param cap Capability to free.
|
|
* \param task If set, task to unmap the capability from.
|
|
* \param unmap_flags Flags for unmap, see l4_unmap_flags_t.
|
|
*/
|
|
virtual void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
|
|
unsigned unmap_flags = L4_FP_ALL_SPACES) noexcept = 0;
|
|
virtual bool release(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
|
|
unsigned unmap_flags = L4_FP_ALL_SPACES) noexcept = 0;
|
|
|
|
/**
|
|
* \brief Destructor.
|
|
*/
|
|
virtual ~Cap_alloc() = 0;
|
|
};
|
|
|
|
template<typename ALLOC>
|
|
struct Cap_alloc_t : ALLOC, L4Re::Cap_alloc
|
|
{
|
|
template<typename ...ARGS>
|
|
Cap_alloc_t(ARGS &&...args) : ALLOC(cxx::forward<ARGS>(args)...) {}
|
|
|
|
L4::Cap<void> alloc() noexcept override { return ALLOC::alloc(); }
|
|
void take(L4::Cap<void> cap) noexcept override { ALLOC::take(cap); }
|
|
|
|
template <typename T>
|
|
L4::Cap<T> alloc() noexcept
|
|
{
|
|
return L4::cap_cast<T>(alloc());
|
|
}
|
|
|
|
void free(L4::Cap<void> cap, l4_cap_idx_t task = L4_INVALID_CAP,
|
|
unsigned unmap_flags = L4_FP_ALL_SPACES) noexcept override
|
|
{ ALLOC::free(cap, task, unmap_flags); }
|
|
|
|
bool release(L4::Cap<void> cap, l4_cap_idx_t task,
|
|
unsigned unmap_flags) noexcept override
|
|
{ return ALLOC::release(cap, task, unmap_flags); }
|
|
|
|
void operator delete(void *) {}
|
|
};
|
|
|
|
inline
|
|
Cap_alloc::~Cap_alloc()
|
|
{}
|
|
|
|
extern Cap_alloc *virt_cap_alloc;
|
|
|
|
/**
|
|
* \brief Helper for Unique_cap and Unique_del_cap
|
|
* \ingroup api_l4re_util
|
|
*/
|
|
template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
|
|
class Smart_cap_auto
|
|
{
|
|
private:
|
|
Cap_alloc *_ca;
|
|
|
|
public:
|
|
Smart_cap_auto() : _ca(0) {}
|
|
Smart_cap_auto(Cap_alloc *ca) : _ca(ca) {}
|
|
|
|
void free(L4::Cap_base &c)
|
|
{
|
|
if (c.is_valid() && _ca)
|
|
_ca->free(L4::Cap<void>(c.cap()), This_task, Unmap_flags);
|
|
|
|
invalidate(c);
|
|
}
|
|
|
|
static void invalidate(L4::Cap_base &c)
|
|
{
|
|
if (c.is_valid())
|
|
c.invalidate();
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* Helper for Ref_cap and Ref_del_cap.
|
|
*/
|
|
template< unsigned long Unmap_flags = L4_FP_ALL_SPACES >
|
|
class Smart_count_cap
|
|
{
|
|
private:
|
|
Cap_alloc *_ca;
|
|
|
|
public:
|
|
Smart_count_cap() : _ca(nullptr) {}
|
|
Smart_count_cap(Cap_alloc *ca) : _ca(ca) {}
|
|
/**
|
|
* Free operation for L4::Smart_cap
|
|
* (decrement ref count and delete if 0).
|
|
*/
|
|
void free(L4::Cap_base &c) noexcept
|
|
{
|
|
if (c.is_valid())
|
|
{
|
|
if (_ca && _ca->release(L4::Cap<void>(c.cap()), This_task, Unmap_flags))
|
|
c.invalidate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invalidate operation for L4::Smart_cap.
|
|
*/
|
|
static void invalidate(L4::Cap_base &c) noexcept
|
|
{
|
|
if (c.is_valid())
|
|
c.invalidate();
|
|
}
|
|
|
|
/**
|
|
* Copy operation for L4::Smart_cap (increment ref count).
|
|
*/
|
|
L4::Cap_base copy(L4::Cap_base const &src)
|
|
{
|
|
if (src.is_valid())
|
|
_ca->take(L4::Cap<void>(src.cap()));
|
|
return src;
|
|
}
|
|
};
|
|
/**@}*/
|
|
|
|
}
|