568 lines
15 KiB
C++
568 lines
15 KiB
C++
// vim:set ft=cpp:
|
|
/**
|
|
* \file
|
|
* \brief L4::Capability class.
|
|
*
|
|
* \author Alexander Warg <alexander.warg@os.inf.tu-dresden.de>
|
|
*
|
|
*/
|
|
/*
|
|
* (c) 2008-2009 Author(s)
|
|
* economic rights: Technische Universität Dresden (Germany)
|
|
*
|
|
* This file is part of TUD:OS and distributed under the terms of the
|
|
* GNU General Public License 2.
|
|
* Please see the COPYING-GPL-2 file for details.
|
|
*
|
|
* As a special exception, you may use this file as part of a free software
|
|
* library without restriction. Specifically, if other files instantiate
|
|
* templates or use macros or inline functions from this file, or you compile
|
|
* this file and link it with other files to produce an executable, this
|
|
* file does not by itself cause the resulting executable to be covered by
|
|
* the GNU General Public License. This exception does not however
|
|
* invalidate any other reasons why the executable file might be covered by
|
|
* the GNU General Public License.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <l4/sys/consts.h>
|
|
#include <l4/sys/types.h>
|
|
#include <l4/sys/kernel_object.h>
|
|
#include <l4/sys/task.h>
|
|
|
|
#include <l4/sys/__typeinfo.h>
|
|
|
|
namespace L4
|
|
{
|
|
|
|
/* Forward declarations for our kernel object classes. */
|
|
class Task;
|
|
class Thread;
|
|
class Factory;
|
|
class Irq;
|
|
class Log;
|
|
class Vm;
|
|
class Kobject;
|
|
|
|
template< typename T > class Cap;
|
|
|
|
/**
|
|
* \addtogroup l4_cap_api
|
|
*
|
|
* C++ interface for capabilities:<br>
|
|
* <c>\#include <l4/sys/capability></c>
|
|
*/
|
|
/*@{*/
|
|
/**
|
|
* \brief Base class for all kinds of capabilities.
|
|
* \attention This class is not for direct use, use L4::Cap instead.
|
|
*
|
|
* This class contains all the things that are independent of the type
|
|
* of the object referred by the capability.
|
|
*
|
|
* \see L4::Cap for typed capabilities.
|
|
*/
|
|
class Cap_base
|
|
{
|
|
private:
|
|
struct Invalid_conversion;
|
|
|
|
public:
|
|
enum No_init_type
|
|
{
|
|
/**
|
|
* \brief Special value for constructing uninitialized Cap objects.
|
|
*/
|
|
No_init
|
|
};
|
|
|
|
/**
|
|
* \brief Invalid capability type.
|
|
*/
|
|
enum Cap_type
|
|
{
|
|
Invalid = L4_INVALID_CAP ///< Invalid capability selector
|
|
};
|
|
|
|
/**
|
|
* \brief Return capability selector.
|
|
* \return Capability selector.
|
|
*/
|
|
l4_cap_idx_t cap() const throw() { return _c; }
|
|
|
|
/**
|
|
* \brief Test whether capability selector is not the invalid capability
|
|
* selector.
|
|
*
|
|
* \return True if capability is not invalid, false if invalid
|
|
*/
|
|
bool is_valid() const throw() { return !(_c & L4_INVALID_CAP_BIT); }
|
|
|
|
operator Invalid_conversion * () const throw()
|
|
{ return (Invalid_conversion*)(!(_c & L4_INVALID_CAP_BIT)); }
|
|
|
|
/**
|
|
* \brief Returns flex-page of the capability selector.
|
|
* \param rights Rights, defaults to 'rwx'
|
|
* \return flex-page
|
|
*/
|
|
l4_fpage_t fpage(unsigned rights = L4_FPAGE_RWX) const throw()
|
|
{ return l4_obj_fpage(_c, 0, rights); }
|
|
|
|
/**
|
|
* \brief Returns send base.
|
|
* \param grant True object should be granted.
|
|
* \param base Base capability selector
|
|
* \return Map object.
|
|
*/
|
|
l4_umword_t snd_base(unsigned grant = 0,
|
|
l4_cap_idx_t base = L4_INVALID_CAP) const throw()
|
|
{
|
|
if (base == L4_INVALID_CAP)
|
|
base = _c;
|
|
return l4_map_obj_control(base, grant);
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Test if two capability selectors are equal.
|
|
*/
|
|
bool operator == (Cap_base const &o) const throw()
|
|
{ return _c == o._c; }
|
|
|
|
/**
|
|
* \brief Test if two capability selectors are not equal.
|
|
*/
|
|
bool operator != (Cap_base const &o) const throw()
|
|
{ return _c != o._c; }
|
|
|
|
/**
|
|
* \brief Check whether a capability selector points to a valid capability.
|
|
*
|
|
* \param u UTCB of the caller
|
|
* \return label = 0 valid, label > 0 invalid
|
|
*/
|
|
inline l4_msgtag_t validate(l4_utcb_t *u = l4_utcb()) const throw();
|
|
|
|
/**
|
|
* \brief Check whether a capability selector points to a valid capability.
|
|
*
|
|
* \param u UTCB of the caller
|
|
* \param task Task to check the capability in
|
|
*
|
|
* \return label = 0 valid, label > 0 invalid
|
|
*/
|
|
inline l4_msgtag_t validate(Cap<Task> task,
|
|
l4_utcb_t *u = l4_utcb()) const throw();
|
|
|
|
/**
|
|
* \brief Set this selector to the invalid capability (L4_INVALID_CAP).
|
|
*/
|
|
void invalidate() throw() { _c = L4_INVALID_CAP; }
|
|
protected:
|
|
/**
|
|
* \brief Generate a capability from its C representation.
|
|
* \param c the C capability selector
|
|
*/
|
|
explicit Cap_base(l4_cap_idx_t c) throw() : _c(c) {}
|
|
/**
|
|
* \brief Constructor to create an invalid capability selector.
|
|
*/
|
|
explicit Cap_base(Cap_type cap) throw() : _c(cap) {}
|
|
|
|
/**
|
|
* \brief Initialize capability with one of the default capability selectors.
|
|
* \param cap Capability selector.
|
|
*/
|
|
explicit Cap_base(l4_default_caps_t cap) throw() : _c(cap) {}
|
|
|
|
/**
|
|
* \brief Create an uninitialized instance.
|
|
*/
|
|
explicit Cap_base() throw() {}
|
|
|
|
/**
|
|
* \brief The C representation of a capability selector. */
|
|
l4_cap_idx_t _c;
|
|
};
|
|
|
|
|
|
/**
|
|
* \brief Capability Selector a la C++.
|
|
* \tparam T the type of the object the capability points to
|
|
*
|
|
* The C++ version of a capability looks just as a pointer, in fact
|
|
* it is a kind of a smart pointer for our kernel objects and the
|
|
* objects derived from the kernel objects (L4::Kobject).
|
|
*/
|
|
template< typename T >
|
|
class Cap : public Cap_base
|
|
{
|
|
private:
|
|
friend class L4::Kobject;
|
|
|
|
/**
|
|
* \internal
|
|
* \brief Internal Constructor, use to generate a capability from a \a this
|
|
* pointer.
|
|
*
|
|
* \attention This constructor is only useful to generate a capability
|
|
* from the \a this pointer of an objected that is an L4::Kobject.
|
|
* Do \em never use this constructor for something else!
|
|
* \param p The \a this pointer of the Kobject or derived object
|
|
*/
|
|
explicit Cap(T const *p) throw()
|
|
: Cap_base(reinterpret_cast<l4_cap_idx_t>(p)) {}
|
|
|
|
public:
|
|
|
|
/**
|
|
* \brief Create a copy from \a o, supporting implicit type casting.
|
|
* \param o is the source selector that shall be copied (and casted).
|
|
*/
|
|
template< typename O >
|
|
Cap(Cap<O> const &o) throw() : Cap_base(o.cap())
|
|
{ register T* __t = ((O*)100); (void)__t; }
|
|
|
|
/**
|
|
* \brief Constructor to create an invalid capability selector.
|
|
*/
|
|
Cap(Cap_type cap) throw() : Cap_base(cap) {}
|
|
|
|
/**
|
|
* \brief Initialize capability with one of the default capability selectors.
|
|
* \param cap Capability selector.
|
|
*/
|
|
Cap(l4_default_caps_t cap) throw() : Cap_base(cap) {}
|
|
|
|
/**
|
|
* \brief Initialize capability, defaults to the invalid capability selector.
|
|
* \param idx Capability selector.
|
|
*/
|
|
explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) throw() : Cap_base(idx) {}
|
|
|
|
/**
|
|
* \brief Create an uninitialized cap selector.
|
|
*/
|
|
explicit Cap(No_init_type) throw() {}
|
|
|
|
/**
|
|
* \brief Move a capability to this cap slot.
|
|
* \param src the source capability slot.
|
|
*
|
|
* After this operation the source slot is no longer valid.
|
|
*/
|
|
Cap move(Cap const &src) const
|
|
{
|
|
if (!is_valid() || !src.is_valid())
|
|
return *this;
|
|
|
|
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_FPAGE_RWX),
|
|
snd_base(L4_MAP_ITEM_GRANT));
|
|
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* \brief Member access of a \a T.
|
|
*/
|
|
T *operator -> () const throw() { return reinterpret_cast<T*>(_c); }
|
|
};
|
|
|
|
|
|
/**
|
|
* \internal
|
|
* \brief Specialization for \a void capabilities.
|
|
*/
|
|
template<>
|
|
class Cap<void> : public Cap_base
|
|
{
|
|
public:
|
|
|
|
explicit Cap(void const *p) throw()
|
|
: Cap_base(reinterpret_cast<l4_cap_idx_t>(p)) {}
|
|
|
|
/**
|
|
* \brief Constructor to create an invalid capability selector.
|
|
*/
|
|
Cap(Cap_type cap) throw() : Cap_base(cap) {}
|
|
|
|
/**
|
|
* \brief Initialize capability with one of the default capability selectors.
|
|
* \param cap Capability selector.
|
|
*/
|
|
Cap(l4_default_caps_t cap) throw() : Cap_base(cap) {}
|
|
|
|
/**
|
|
* \brief Initialize capability, defaults to the invalid capability selector.
|
|
* \param idx Capability selector.
|
|
*/
|
|
explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) throw() : Cap_base(idx) {}
|
|
explicit Cap(No_init_type) throw() {}
|
|
|
|
/**
|
|
* \brief Move a capability to this cap slot.
|
|
* \param src the source capability slot.
|
|
*
|
|
* After this operation the source slot is no longer valid.
|
|
*/
|
|
Cap move(Cap const &src) const
|
|
{
|
|
if (!is_valid() || !src.is_valid())
|
|
return *this;
|
|
|
|
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_FPAGE_RWX),
|
|
snd_base(L4_MAP_ITEM_GRANT));
|
|
|
|
return *this;
|
|
}
|
|
|
|
template< typename T >
|
|
Cap(Cap<T> const &o) throw() : Cap_base(o.cap()) {}
|
|
};
|
|
|
|
/**
|
|
* \brief static_cast for capabilities.
|
|
* \param T is the target type of the capability
|
|
* \param F is the source type (and is usually implicitly set)
|
|
* \param c is the source capability that shall be casted
|
|
* \return A capability typed to the interface \a T.
|
|
*
|
|
* The use of this cast operator is similar to the static_cast<>() for
|
|
* C++ pointers. It does the same type checking and adjustment like
|
|
* C++ does on pointers.
|
|
*
|
|
* Example code:
|
|
* \code
|
|
* L4::Cap<L4::Kobject> obj = ... ;
|
|
* L4::Cap<L4::Icu> icu = L4::cap_cast<L4::Icu>(obj);
|
|
* \endcode
|
|
*/
|
|
template< typename T, typename F >
|
|
inline
|
|
Cap<T> cap_cast(Cap<F> const &c) throw()
|
|
{
|
|
(void)static_cast<T const *>(reinterpret_cast<F const *>(100));
|
|
return Cap<T>(c.cap());
|
|
}
|
|
|
|
/**
|
|
* \brief reinterpret_cast for capabilities.
|
|
* \param T is the target type of the capability
|
|
* \param F is the source type (and is usually implicitly set)
|
|
* \param c is the source capability that shall be casted
|
|
* \return A capability typed to the interface \a T.
|
|
*
|
|
* The use of this cast operator is similar to the reinterpret_cast<>() for
|
|
* C++ pointers. It does not do any type checking or type adjustment.
|
|
*
|
|
* Example code:
|
|
* \code
|
|
* L4::Cap<L4::Kobject> obj = ... ;
|
|
* L4::Cap<L4::Icu> icu = L4::cap_reinterpret_cast<L4::Icu>(obj);
|
|
* \endcode
|
|
*/
|
|
template< typename T, typename F >
|
|
inline
|
|
Cap<T> cap_reinterpret_cast(Cap<F> const &c) throw()
|
|
{
|
|
return Cap<T>(c.cap());
|
|
}
|
|
|
|
/*@}*/
|
|
|
|
/**
|
|
* \addtogroup l4_kernel_object_api
|
|
*
|
|
* <c>\#include <l4/sys/capability></c>
|
|
*/
|
|
/*@{*/
|
|
/**
|
|
* \brief Disable copy of a class.
|
|
* \param _class is the name of the class that shall not have
|
|
* value copy semantics.
|
|
*
|
|
*
|
|
* The typical use of this is:
|
|
* \code
|
|
* class Non_value
|
|
* {
|
|
* L4_DISABLE_COPY(Non_value)
|
|
*
|
|
* ...
|
|
* }
|
|
* \endcode
|
|
*/
|
|
#define L4_DISABLE_COPY(_class) \
|
|
private: \
|
|
_class(_class const &); \
|
|
_class operator = (_class const &);
|
|
|
|
|
|
/**
|
|
* \brief Disable copy and instantiation of a class.
|
|
* \param _class is the name of the class to be not copyable and not
|
|
* instantiatable.
|
|
*
|
|
* The typical use looks like:
|
|
* \code
|
|
* class Type
|
|
* {
|
|
* L4_KOBJECT_DISABLE_COPY(Type)
|
|
* };
|
|
* \endcode
|
|
*/
|
|
#define L4_KOBJECT_DISABLE_COPY(_class) \
|
|
protected: \
|
|
_class(); \
|
|
L4_DISABLE_COPY(_class)
|
|
|
|
|
|
/**
|
|
* \brief Declare a kernel object class.
|
|
* \param _class is the class name.
|
|
*
|
|
* The use of this macro disables copy and instantiation
|
|
* of the class as needed for kernel object classes derived from
|
|
* L4::Kobject.
|
|
*
|
|
* The typical use looks like:
|
|
* \code
|
|
* class Type : public L4::Kobject_t<Type, L4::Kobject>
|
|
* {
|
|
* L4_KOBJECT(Type)
|
|
* };
|
|
* \endcode
|
|
*/
|
|
#define L4_KOBJECT(_class) L4_KOBJECT_DISABLE_COPY(_class)
|
|
|
|
|
|
/**
|
|
* \ingroup l4_kernel_object_api
|
|
* \brief Base class for all kinds of kernel objects, referred to by
|
|
* capabilities.
|
|
*
|
|
* <c>\#include <l4/sys/capability></c>
|
|
*
|
|
* \attention Objects derived from Kobject \em must never add any data to
|
|
* those objects. Kobjects can act only as proxy object
|
|
* for encapsulating object invocations.
|
|
*/
|
|
class Kobject
|
|
{
|
|
L4_KOBJECT(Kobject)
|
|
|
|
private:
|
|
|
|
template<typename T>
|
|
friend Type_info const *kobject_typeid();
|
|
|
|
protected:
|
|
/**
|
|
* \internal
|
|
* \brief Get a pointer to the L4Re dynamic type information
|
|
* for this class.
|
|
*
|
|
* \note This function is used by L4::kobject_typeid().
|
|
*/
|
|
struct __Kobject_typeid { static Type_info const _m; };
|
|
|
|
/**
|
|
* \brief Return capability selector.
|
|
* \return Capability selector.
|
|
*
|
|
* This method is for derived classes to gain access to the actual
|
|
* capability selector.
|
|
*/
|
|
l4_cap_idx_t cap() const throw() { return _c(); }
|
|
|
|
private:
|
|
|
|
/**
|
|
* \internal
|
|
* \brief Used to convert the \c this pointer to a capability selector.
|
|
*/
|
|
l4_cap_idx_t _c() const throw()
|
|
{ return reinterpret_cast<l4_cap_idx_t>(this) & L4_CAP_MASK; }
|
|
|
|
public:
|
|
/**
|
|
* \brief Decrement the in kernel reference counter for the object.
|
|
* \param diff is the delta that shall be subtracted from the reference
|
|
* count.
|
|
* \param utcb is the utcb to use for the invocation.
|
|
*
|
|
* This function is intended for servers to be able to remove the servers
|
|
* own capability from the counted references. This leads to the semantics
|
|
* that the kernel will delete the object even if the capability of the
|
|
* server is valid. The server can detect the deletion by polling its
|
|
* capabilities or by using the IPC-gate deletion IRQs. And to cleanup
|
|
* if the clients dropped the last reference (capability) to the object.
|
|
*/
|
|
l4_msgtag_t dec_refcnt(l4_mword_t diff, l4_utcb_t *utcb = l4_utcb())
|
|
{ return l4_kobject_dec_refcnt_u(cap(), diff, utcb); }
|
|
};
|
|
|
|
/*@}*/
|
|
|
|
inline l4_msgtag_t
|
|
Cap_base::validate(Cap<Task> task, l4_utcb_t *u) const throw()
|
|
{ return l4_task_cap_valid_u(task.cap(), _c, u); }
|
|
|
|
inline l4_msgtag_t
|
|
Cap_base::validate(l4_utcb_t *u) const throw()
|
|
{ return l4_task_cap_valid_u(L4_BASE_TASK_CAP, _c, u); }
|
|
|
|
}; // namespace L4
|
|
|
|
#include <l4/sys/meta>
|
|
|
|
namespace L4 {
|
|
|
|
/**
|
|
* \addtogroup l4_cap_api
|
|
*/
|
|
/*@{*/
|
|
/**
|
|
* \brief dynamic_cast for capabilities.
|
|
* \param T is the target type of the capability
|
|
* \param F is the source type (and is usually implicitly set)
|
|
* \param c is the source capability that shall be casted
|
|
* \return A capability typed to the interface \a T. If the object does not
|
|
* support the target interface \a T or does not support the
|
|
* L4::Meta interface the result is the invalid capability selector.
|
|
*
|
|
* The use of this cast operator is similar to the dynamic_cast<>() for
|
|
* C++ pointers. It also induces overhead, because it uses the meta interface
|
|
* (L4::Meta) to do runtime type checking.
|
|
*
|
|
* Example code:
|
|
* \code
|
|
* L4::Cap<L4::Kobject> obj = ... ;
|
|
* L4::Cap<L4::Icu> icu = L4::cap_dynamic_cast<L4::Icu>(obj);
|
|
* \endcode
|
|
*/
|
|
template< typename T, typename F >
|
|
inline
|
|
Cap<T> cap_dynamic_cast(Cap<F> const &c) throw()
|
|
{
|
|
if (!c.is_valid())
|
|
return Cap<T>::Invalid;
|
|
|
|
Cap<Meta> mc = cap_reinterpret_cast<Meta>(c);
|
|
Type_info const *m = kobject_typeid<T>();
|
|
if (m->proto() && l4_error(mc->supports(m->proto())) > 0)
|
|
return Cap<T>(c.cap());
|
|
|
|
// FIXME: use generic checker
|
|
#if 0
|
|
if (l4_error(mc->supports(T::kobject_proto())) > 0)
|
|
return Cap<T>(c.cap());
|
|
#endif
|
|
|
|
return Cap<T>::Invalid;
|
|
}
|
|
|
|
/*@}*/
|
|
}
|