]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/kobject.cpp
e5b3c86002290ad0f722eabaebf684f69695ce3b
[l4.git] / kernel / fiasco / src / kern / kobject.cpp
1 INTERFACE:
2
3 #include "lock.h"
4 #include "obj_space.h"
5 #include <hlist>
6
7
8 class Kobject_mappable
9 {
10 private:
11   friend class Kobject_mapdb;
12   friend class Jdb_mapdb;
13
14   Obj::Mapping::List _root;
15   Smword _cnt;
16   Lock _lock;
17
18 public:
19   Kobject_mappable() : _cnt(0) {}
20   bool no_mappings() const { return _root.empty(); }
21
22   /**
23    * Insert the root mapping of an object.
24    */
25   template<typename M>
26   bool insert(void *, Space *, M &m)
27   {
28     m._c->put_as_root();
29     _root.add(m._c);
30     _cnt = 1;
31     return true;
32   }
33
34   Smword cap_ref_cnt() const { return _cnt; }
35 };
36
37
38 //----------------------------------------------------------------------------
39 INTERFACE:
40
41 #include "context.h"
42 #include "kobject_dbg.h"
43 #include "kobject_iface.h"
44 #include "l4_error.h"
45 #include "rcupdate.h"
46 #include "space.h"
47
48 class Kobject :
49   public Kobject_iface,
50   private Kobject_mappable,
51   private Kobject_dbg
52 {
53   template<typename T>
54   friend class Map_traits;
55
56 private:
57   template<typename T>
58   class Tconv {};
59
60   template<typename T>
61   class Tconv<T*> { public: typedef T Base; };
62
63 public:
64   template<typename T>
65   static T dcast(Kobject_common *_o)
66   {
67     if (EXPECT_FALSE(!_o))
68       return 0;
69
70     if (EXPECT_TRUE(_o->kobj_type() == Tconv<T>::Base::static_kobj_type))
71       return reinterpret_cast<T>(_o->kobject_start_addr());
72     return 0;
73   }
74
75   template<typename T>
76   static T dcast(Kobject_common const *_o)
77   {
78     if (EXPECT_FALSE(!_o))
79       return 0;
80
81     if (EXPECT_TRUE(_o->kobj_type() == Tconv<T>::Base::static_kobj_type))
82       return reinterpret_cast<T>(_o->kobject_start_addr());
83     return 0;
84   }
85
86   using Kobject_dbg::dbg_id;
87
88   Lock existence_lock;
89
90 public:
91   Kobject *_next_to_reap;
92
93 public:
94   enum Op {
95     O_dec_refcnt = 0,
96   };
97
98 };
99
100 #define FIASCO_DECLARE_KOBJ() \
101   public: static char const *const static_kobj_type; \
102           char const *kobj_type() const; \
103           Address kobject_start_addr() const; \
104           Mword kobject_size() const;
105
106 #define FIASCO_DEFINE_KOBJ(t) \
107   char const *const t::static_kobj_type = #t; \
108   char const *t::kobj_type() const { return static_kobj_type; } \
109   Address t::kobject_start_addr() const { return (Address)this; } \
110   Mword t::kobject_size() const { return sizeof(*this); }
111
112
113 //---------------------------------------------------------------------------
114 IMPLEMENTATION:
115
116 #include "logdefs.h"
117 #include "l4_buf_iter.h"
118 #include "lock_guard.h"
119
120
121 PUBLIC bool  Kobject::is_local(Space *) const { return false; }
122 PUBLIC Mword Kobject::obj_id() const { return ~0UL; }
123 PUBLIC virtual bool  Kobject::put() { return true; }
124 PUBLIC Kobject_mappable *Kobject::map_root() { return this; }
125
126 PUBLIC inline NEEDS["lock_guard.h"]
127 Smword
128 Kobject_mappable::dec_cap_refcnt(Smword diff)
129 {
130   auto g = lock_guard(_lock);
131   _cnt -= diff;
132   return _cnt;
133 }
134
135 PUBLIC
136 void
137 Kobject::initiate_deletion(Kobject ***reap_list)
138 {
139   existence_lock.invalidate();
140
141   _next_to_reap = 0;
142   **reap_list = this;
143   *reap_list = &_next_to_reap;
144 }
145
146 PUBLIC virtual
147 void
148 Kobject::destroy(Kobject ***)
149 {
150   LOG_TRACE("Kobject destroy", "des", current(), Log_destroy,
151       l->id = dbg_id();
152       l->obj = this;
153       l->type = kobj_type());
154   existence_lock.wait_free();
155 }
156
157 PUBLIC virtual
158 Kobject::~Kobject()
159 {
160   LOG_TRACE("Kobject delete (generic)", "del", current(), Log_destroy,
161       l->id = dbg_id();
162       l->obj = this;
163       l->type = "unk");
164 }
165
166
167 PRIVATE inline NOEXPORT
168 L4_msg_tag
169 Kobject::sys_dec_refcnt(L4_msg_tag tag, Utcb const *in, Utcb *out)
170 {
171   if (tag.words() < 2)
172     return Kobject_iface::commit_result(-L4_err::EInval);
173
174   Smword diff = in->values[1];
175   out->values[0] = dec_cap_refcnt(diff);
176   return Kobject_iface::commit_result(0);
177 }
178
179 PUBLIC
180 L4_msg_tag
181 Kobject::kobject_invoke(L4_obj_ref, Mword /*rights*/,
182                         Syscall_frame *f,
183                         Utcb const *in, Utcb *out)
184 {
185   L4_msg_tag tag = f->tag();
186
187   if (EXPECT_FALSE(tag.words() < 1))
188     return Kobject_iface::commit_result(-L4_err::EInval);
189
190   switch (in->values[0])
191     {
192     case O_dec_refcnt:
193       return sys_dec_refcnt(tag, in, out);
194     default:
195       return Kobject_iface::commit_result(-L4_err::ENosys);
196     }
197
198 }
199
200 //---------------------------------------------------------------------------
201 INTERFACE [debug]:
202
203 #include "tb_entry.h"
204
205 EXTENSION class Kobject
206 {
207 protected:
208   struct Log_destroy : public Tb_entry
209   {
210     Kobject    *obj;
211     Mword       id;
212     char const *type;
213     Mword       ram;
214     unsigned print(int max, char *buf) const;
215   };
216 };
217
218 //---------------------------------------------------------------------------
219 IMPLEMENTATION [debug]:
220
221 PUBLIC static inline
222 Kobject *
223 Kobject::from_dbg(Kobject_dbg *d)
224 { return static_cast<Kobject*>(d); }
225
226 PUBLIC static inline
227 Kobject *
228 Kobject::from_dbg(Kobject_dbg::Iterator const &d)
229 {
230   if (d != Kobject_dbg::end())
231     return static_cast<Kobject*>(*d);
232   return 0;
233 }
234
235 PUBLIC
236 Kobject_dbg *
237 Kobject::dbg_info() const
238 { return const_cast<Kobject*>(this); }
239
240 IMPLEMENT
241 unsigned
242 Kobject::Log_destroy::print(int max, char *buf) const
243 {
244   return snprintf(buf, max, "obj=%lx [%s] (%p) ram=%lx", id, type, obj, ram);
245 }