]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx_thread/src/thread.cc
update
[l4.git] / l4 / pkg / cxx_thread / src / thread.cc
1 /*
2  * (c) 2004-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU Lesser General Public License 2.1.
7  * Please see the COPYING-LGPL-2.1 file for details.
8  */
9
10 #include <l4/cxx/thread>
11 #include <l4/cxx/iostream>
12 #include <l4/cxx/l4iostream>
13
14 #include <l4/sys/thread>
15 #include <l4/sys/factory>
16 #include <l4/sys/scheduler>
17 #include <l4/sys/ipc.h>
18
19 #include <l4/util/util.h>
20 #include <l4/re/env>
21
22 #include <l4/cxx/ipc_stream>
23
24
25 namespace cxx {
26
27   namespace {
28     l4_cap_idx_t _next_cap = 20 << L4_CAP_SHIFT;
29     static inline l4_cap_idx_t alloc_next_cap()
30     { l4_cap_idx_t r = _next_cap; _next_cap += (1UL << L4_CAP_SHIFT); return r; }
31     l4_addr_t _next_free_utcb;
32     l4_addr_t _utcb_base;
33   };
34
35   L4::Cap<void> Thread::_pager;
36   L4::Cap<void> Thread::_master;
37
38   Thread::Thread( bool /*initiate*/ )
39     : _cap(L4Re::Env::env()->main_thread()), _state(Running)
40   {
41     _next_free_utcb = L4Re::Env::env()->first_free_utcb();
42     _master = _cap;
43     L4::Thread::Attr attr;
44     _cap->control(attr);
45     _pager = attr.pager();
46     _utcb_base = l4_addr_t(l4_utcb());
47   }
48
49   int
50   Thread::create()
51   {
52     l4_msgtag_t err = L4Re::Env::env()->factory()->create_thread(_cap);
53     if (l4_msgtag_has_error(err) || l4_msgtag_label(err) < 0)
54       return l4_msgtag_label(err);
55
56     L4::Thread::Attr attr(l4_utcb());
57     attr.pager(_pager);
58     attr.bind((l4_utcb_t*)_next_free_utcb, L4Re::This_task);
59     _next_free_utcb += L4_UTCB_OFFSET;
60     return _cap->control(attr).label();
61   }
62
63   Thread::Thread( void *stack )
64     : _cap(alloc_next_cap()), _state(Dead), _stack(stack)
65   {
66     create();
67   }
68
69   Thread::Thread( void *stack, L4::Cap<L4::Thread> const &cap )
70     : _cap(cap), _state(Dead), _stack(stack)
71   {
72     create();
73   }
74
75   void Thread::start()
76   {
77     if(_cap == _master) {
78       _state = Running;
79       run();
80     } else {
81
82       L4Re::Env::env()->scheduler()->
83             run_thread(_cap, l4_sched_param(0xff, 0));
84
85       *(--((l4_umword_t*&)_stack)) = (l4_umword_t)this;
86       *(--((l4_umword_t*&)_stack)) = 0;
87       _cap->ex_regs((l4_umword_t)start_cxx_thread,
88                     (l4_umword_t)_stack, 0);
89
90       if (l4_msgtag_has_error(l4_ipc_send(_cap.cap(), l4_utcb(),
91                                           l4_msgtag(0,0,0,0),
92                                           L4_IPC_NEVER)))
93         L4::cerr << "ERROR: (master) error while thread handshake: "
94                  << _master << "->" << self() << "\n";
95     }
96   }
97
98   void Thread::execute()
99   {
100     l4_umword_t src;
101     l4_msgtag_t tag = l4_ipc_wait(l4_utcb(), &src, L4_IPC_NEVER);
102
103     if (l4_msgtag_has_error(tag))
104       L4::cerr << "ERROR: (slave) error while thread handshake: "
105                << self() << "\n";
106     _state = Running;
107     run();
108     shutdown();
109   };
110
111   void Thread::shutdown()
112   {
113     _state = Stopped;
114     for (;;)
115       l4_ipc_sleep(L4_IPC_NEVER);
116   }
117
118   void Thread::stop()
119   {
120 #if 0
121     L4::cerr << "~Thread[" << self() << "]() called from "
122              << l4_myself() << " @" << L4::hex
123              << __builtin_return_address(0) << "\n";
124 #endif
125     if(_cap != _master)
126       {
127         *(((l4_umword_t*&)_stack)--) = (l4_umword_t)this;
128         _cap->ex_regs((l4_umword_t)kill_cxx_thread,
129                       (l4_umword_t)_stack, 0);
130       }
131   }
132
133   Thread::~Thread()
134   { stop(); }
135
136 };