]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/kobject_helper.cpp
update
[l4.git] / kernel / fiasco / src / kern / kobject_helper.cpp
1 INTERFACE:
2
3 #include "kobject.h"
4 #include "thread.h"
5
6 class Kobject_helper_base
7 {
8 protected:
9   static Mword _utcb_dummy[];
10   static Utcb *utcb_dummy()
11   {
12     char *x = reinterpret_cast<char*>(&_utcb_dummy);
13     return reinterpret_cast<Utcb*>(x);
14   }
15
16   static L4_msg_tag no_reply() { return L4_msg_tag(L4_msg_tag::Schedule); }
17   static bool have_receive(Utcb *rcv) { return rcv != utcb_dummy(); }
18 };
19
20 template<typename T, typename Base = Kobject>
21 class Kobject_h : public Base, protected Kobject_helper_base
22 {
23 private:
24   static Sender *_sender(Thread *, Sender *t) { return t; }
25   static Sender *_sender(Thread *ct, ...) { return ct; }
26
27 public:
28
29   explicit Kobject_h() : Base() {}
30
31   template< typename A >
32   explicit Kobject_h(A a) : Base(a) {}
33
34   void invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *u)
35   {
36     L4_msg_tag res(0);
37     if (EXPECT_TRUE(self.op() & L4_obj_ref::Ipc_send))
38       res = static_cast<T*>(this)->T::kinvoke(self, rights, f, (Utcb const *)u,
39                                               self.have_recv() ? u : utcb_dummy());
40
41     if (EXPECT_FALSE(res.has_error()))
42       {
43         f->tag(res);
44         return;
45       }
46
47     if (self.have_recv())
48       {
49         if (!res.do_switch())
50           {
51             Thread *t = current_thread();
52             Sender *s = (self.op() & L4_obj_ref::Ipc_open_wait) ? 0 : _sender(t, static_cast<T*>(this));
53             t->do_ipc(f->tag(), 0, 0, true, s, f->timeout(), f, rights);
54             return;
55           }
56         else
57           f->tag(res);
58       }
59   }
60
61 };
62
63
64 IMPLEMENTATION:
65
66 Mword Kobject_helper_base::_utcb_dummy[(sizeof(Utcb) + sizeof(Mword) - 1) / sizeof(Mword)];
67