// vi:ft=cpp /* * (c) 2008-2009 Adam Lackorzynski , * Alexander Warg * 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 #include #include #include #include #include #include namespace L4Re { namespace Util { class Dbg; class Err; namespace Names { /** * \brief Name class. */ class Name : public cxx::String { public: Name(const char *name = "") : String(name, __builtin_strlen(name)) {} Name(const char *name, unsigned long len) : String(name, len) {} Name(cxx::String const &n) : String(n) {} char const *name() const { return start(); } bool operator < (Name const &r) const; }; /** * \internal */ class Obj { protected: unsigned _f; union { l4_cap_idx_t _cap; L4::Server_object *_obj; }; public: enum Flags { F_rw = L4Re::Namespace::Rw, F_strong = L4Re::Namespace::Strong, F_trusted = L4Re::Namespace::Trusted, F_rights_mask = F_rw | F_strong | F_trusted, F_cap = 0x100, F_local = 0x200, F_replacable = 0x400, F_base_mask = 0xf00, }; unsigned flags() const { return _f; } void restrict_flags(unsigned max_rights) { _f &= (~F_rights_mask | (max_rights & F_rights_mask)); } bool is_rw() const { return _f & F_rw; } bool is_strong() const { return _f & F_strong; } bool is_valid() const { return _f & F_cap; } bool is_complete() const { return is_valid(); } bool is_local() const { return _f & F_local; } bool is_replacable() const { return _f & F_replacable; } bool is_trusted() const { return _f & F_trusted; } L4::Server_object *obj() const { if (is_local()) return _obj; return 0; } L4::Cap cap() const { if (!is_local()) return L4::Cap(_cap); if (!_obj) return L4::Cap::Invalid; return _obj->obj_cap(); } void set(Obj const &o, unsigned flags) { *this = o; restrict_flags(flags); } explicit Obj(unsigned flags = 0) : _f(flags), _cap(L4_INVALID_CAP) {} Obj(unsigned f, L4::Cap const &cap) : _f((f & ~F_base_mask) | F_cap), _cap(cap.cap()) {} Obj(unsigned f, L4::Server_object *o) : _f((f & ~F_base_mask) | F_cap | F_local), _obj(o) {} void reset(unsigned flags) { _f = (_f & F_replacable) | (flags & ~(F_cap | F_local)); _cap = L4_INVALID_CAP; } }; /** * \internal */ class Entry : public cxx::Avl_tree_node { private: friend class Name_space; Name _n; Obj _o; Entry *_next_link; bool _dynamic; public: Entry(Name const &n, Obj const &o, bool dynamic = false) : _n(n), _o(o), _next_link(0), _dynamic(dynamic) {} Name const &name() const { return _n; } Obj const *obj() const { return &_o; } Obj *obj() { return &_o; } void obj(Obj const &o) { _o = o; } Entry *next_link() const { return _next_link; } void add_link(Entry *o) { o->_next_link = _next_link; _next_link = o; } void set_next_link(Entry *o) { _next_link = o; } bool is_placeholder() const { return !obj()->is_complete(); } bool is_dynamic() const { return _dynamic; } bool link(Entry *src); void set(Obj const &o); private: void * operator new (size_t s); void operator delete(void *b); }; struct Names_get_key { typedef Name Key_type; static Key_type const &key_of(Entry const *e) { return e->name(); } }; /** * \internal */ class Name_space { friend class Entry; private: typedef cxx::Avl_tree Tree; Tree _tree; protected: L4Re::Util::Dbg const &_dbg; L4Re::Util::Err const &_err; public: typedef Tree::Const_iterator Const_iterator; Const_iterator begin() const { return _tree.begin(); } Const_iterator end() const { return _tree.end(); } Name_space(L4Re::Util::Dbg const &dbg, L4Re::Util::Err const &err) : _dbg(dbg), _err(err) {} virtual ~Name_space() {} Entry *find(Name const &name) const { return _tree.find_node(name); } Entry *remove(Name const &name) { return _tree.remove(name); } Entry *find_iter(Name const &name) const; int insert(Entry *e) { return _tree.insert(e).second; } void dump(bool rec = false, int indent = 0) const; protected: // server support -------------------------------------------- virtual Entry *alloc_dynamic_entry(Name const &n, unsigned flags) = 0; virtual void free_dynamic_entry(Entry *e) = 0; virtual int get_capability(L4::Snd_fpage const &cap_fp, L4::Cap *cap, L4::Server_object **lo = 0) = 0; virtual int save_capability(L4::Cap *cap) = 0; virtual void free_capability(L4::Cap cap) = 0; int insert_entry(Name const &name, unsigned flags, Entry **e); public: // server interface ------------------------------------------ int query(L4::Ipc_iostream &ios, char *buffer, size_t blen); int link_entry(L4::Ipc_iostream &ios, char *buffer, size_t blen); int register_entry(L4::Ipc_iostream &ios, char *buffer, size_t blen); int unlink_entry(L4::Ipc_iostream &ios, char *buffer, size_t max_len); int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios, char *buffer, size_t blen); }; }}}