]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx_thread/src/thread.cc
7049929011906abe09453ca0c81c21ca4a06beaa
[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/ipc.h>
17
18 #include <l4/util/util.h>
19 #include <l4/re/env>
20
21 #include <l4/cxx/ipc_stream>
22
23
24 namespace cxx {
25
26   namespace {
27     l4_cap_idx_t _next_cap = 20 << L4_CAP_SHIFT;
28     static inline l4_cap_idx_t alloc_next_cap()
29     { l4_cap_idx_t r = _next_cap; _next_cap += (1UL << L4_CAP_SHIFT); return r; }
30     l4_addr_t _next_free_utcb;
31     l4_addr_t _utcb_base;
32   };
33
34   L4::Cap<void> Thread::_pager;
35   L4::Cap<void> Thread::_master;
36   L4::Cap<void> Thread::_preempter;
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     _preempter = attr.scheduler();
47     _utcb_base = l4_addr_t(l4_utcb());
48   }
49
50   int
51   Thread::create()
52   {
53     l4_msgtag_t err = L4Re::Env::env()->factory()->create_thread(_cap);
54     if (l4_msgtag_has_error(err) || l4_msgtag_label(err) < 0)
55       return l4_msgtag_label(err);
56
57     L4::Thread::Attr attr(l4_utcb());
58     attr.pager(_pager);
59     attr.scheduler(_preempter);
60     attr.bind((l4_utcb_t*)_next_free_utcb, L4Re::This_task);
61     _next_free_utcb += L4_UTCB_OFFSET;
62     return _cap->control(attr).label();
63   }
64
65   Thread::Thread( void *stack )
66     : _cap(alloc_next_cap()), _state(Dead), _stack(stack)
67   {
68     create();
69   }
70
71   Thread::Thread( void *stack, L4::Cap<L4::Thread> const &cap )
72     : _cap(cap), _state(Dead), _stack(stack)
73   {
74     create();
75   }
76
77   void Thread::start()
78   {
79     if(_cap == _master) {
80       _state = Running;
81       run();
82     } else {
83       *(--((l4_umword_t*&)_stack)) = (l4_umword_t)this;
84       *(--((l4_umword_t*&)_stack)) = 0;
85       _cap->ex_regs((l4_umword_t)start_cxx_thread,
86                     (l4_umword_t)_stack, 0);
87
88       if (l4_msgtag_has_error(l4_ipc_send(_cap.cap(), l4_utcb(),
89                                           l4_msgtag(0,0,0,0),
90                                           L4_IPC_NEVER)))
91         L4::cerr << "ERROR: (master) error while thread handshake: "
92                  << _master << "->" << self() << "\n";
93     }
94   }
95
96   void Thread::execute()
97   {
98     l4_umword_t src;
99     l4_msgtag_t tag = l4_ipc_wait(l4_utcb(), &src, L4_IPC_NEVER);
100
101     if (l4_msgtag_has_error(tag))
102       L4::cerr << "ERROR: (slave) error while thread handshake: "
103                << self() << "\n";
104     _state = Running;
105     run();
106     shutdown();
107   };
108
109   void Thread::shutdown()
110   {
111     _state = Stopped;
112     for (;;)
113       l4_ipc_sleep(L4_IPC_NEVER);
114   }
115
116   void Thread::stop()
117   {
118 #if 0
119     L4::cerr << "~Thread[" << self() << "]() called from "
120              << l4_myself() << " @" << L4::hex
121              << __builtin_return_address(0) << "\n";
122 #endif
123     if(_cap != _master)
124       {
125         *(((l4_umword_t*&)_stack)--) = (l4_umword_t)this;
126         _cap->ex_regs((l4_umword_t)kill_cxx_thread,
127                       (l4_umword_t)_stack, 0);
128       }
129   }
130
131   Thread::~Thread()
132   { stop(); }
133
134 };