]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/fault_handlers/syscalls_factory.h
update
[l4.git] / l4 / pkg / plr / server / src / fault_handlers / syscalls_factory.h
1 #pragma once
2
3 /*
4  * syscalls_factory.h --
5  *
6  *     Implementation of the factory system call
7  *
8  * (c) 2012 Björn Döbel <doebel@os.inf.tu-dresden.de>,
9  *     economic rights: Technische Universität Dresden (Germany)
10  * This file is part of TUD:OS and distributed under the terms of the
11  * GNU General Public License 2.
12  * Please see the COPYING-GPL-2 file for details.
13  */
14
15
16 #include "syscalls_handler.h"
17 #include <l4/util/bitops.h>
18
19 namespace Romain
20 {
21
22
23 /*
24  * Handler for factory system calls.
25  * 
26  * This class deals mainly with thread and IRQ objects and keeps track
27  * of their capabilities.
28  */
29 class Factory : public SyscallHandler
30 {
31         /* Trace CAP -> thread mappings
32          * 
33          * This allows us to easily find the thread group belonging to a
34          * capability (which in reality maps to the gate agent IPC gate)
35          */
36         std::map<unsigned, Romain::Thread_group*> _threads;
37         unsigned _thread_count;
38
39         unsigned _irqbits[16]; // trace if certain caps are IRQ objects
40
41         void create_thread(Romain::App_instance *i,
42                            Romain::App_thread *t,
43                            Romain::Thread_group *tg,
44                            Romain::App_model *a,
45                            l4_umword_t cap)
46         {
47                 char threadname[24];
48                 // writing this in C is sooo much shorter than creating a stringbuf...
49                 snprintf(threadname, 24, "thread%d", _thread_count);
50
51                 cap >>= L4_CAP_SHIFT;
52
53                 MSG() << "Creating new thread! " << _threads.size();
54                 MSG() << "CAP: " << std::hex << cap;
55                 Romain::Thread_group* newgroup =
56                         Romain::_the_instance_manager->create_thread_group(0, 0, threadname,
57                                                                                                                            cap, _thread_count);
58                 MSG() << "Group @ " << (void*)newgroup;
59
60                 _thread_count++;
61                 _threads[cap] = newgroup;
62
63                 /* We launch the replica threads now. At this point we must have
64                  * made sure that all faults raised by these threads will be resolved,
65                  * because we cannot be sure if they run before or after any subsequent
66                  * code. */
67                 unsigned cnt = 0;
68                 for (std::vector<Romain::App_thread*>::const_iterator it = newgroup->threads.begin();
69                          it != newgroup->threads.end(); ++it)
70                 {
71                         (*it)->start();
72                 }
73
74                 t->vcpu()->r()->ax = l4_msgtag(0, 1, 0, 0).raw;
75                 //enter_kdebug("created thread");
76         }
77
78
79         /*
80          * Create IRQ and store that this cap is an IRQ.
81          */
82         void create_irq(Romain::App_instance *i,
83                         Romain::App_thread *t,
84                         Romain::Thread_group *tg,
85                         Romain::App_model *a,
86                         l4_umword_t cap)
87         {
88                 DEBUG() << "Creating IRQ with cap " << std::hex << (cap >> L4_CAP_SHIFT);
89                 mark_irq((cap >> L4_CAP_SHIFT) - Romain::FIRST_REPLICA_CAP);
90                 L4::Cap<L4::Irq> irqcap(cap);
91                 t->vcpu()->r()->ax = L4Re::Env::env()->factory()->create_irq(irqcap).raw;
92     }
93
94
95         /*
96          * Store that the given cap points to an IRQ object
97          */
98         void mark_irq(unsigned cap)
99         {
100                 DEBUG() << "cap = " << std::hex << cap;
101                 unsigned *dest  = _irqbits;
102                 dest           += cap / (sizeof(*dest) * 8);
103                 cap            &= sizeof(*dest) * 8 - 1;
104                 *dest          |= (1 << cap);
105         }
106
107         public:
108                 Factory()
109                         : SyscallHandler(), _threads(), _thread_count(0)
110                 { }
111
112                 virtual
113                 Romain::Observer::ObserverReturnVal
114                 handle(Romain::App_instance *i,
115                        Romain::App_thread *t,
116                        Romain::Thread_group *tg,
117                        Romain::App_model *a);
118
119
120                 void register_thread_group(Romain::Thread_group* tg, l4_umword_t cap)
121                 {
122                         _check(cap < Romain::FIRST_REPLICA_CAP, "invalid replica #");
123                         _thread_count++;
124                         _threads[cap] = tg;
125                         DEBUG() << std::hex << cap << " := " << (void*)_threads[cap];
126                 }
127
128
129                 /*
130                  * Get the Thread_group to an agent's gate.
131                  */
132                 Romain::Thread_group* thread_for_cap(l4_umword_t cap)
133                 {
134                         DEBUG() << std::hex << cap << " -> " << (void*)_threads[cap];
135                         return _threads[cap];
136                 }
137
138
139                 /*
140                  * Figure out if a cap belongs to an IRQ object (that was created
141                  * through this factory.
142                  */
143                 bool is_irq(unsigned cap)
144                 {
145                         cap            >>= L4_CAP_SHIFT;
146                         if (cap < Romain::FIRST_REPLICA_CAP) {
147                                 return false;
148                         }
149                         cap             -= Romain::FIRST_REPLICA_CAP;
150
151                         DEBUG() << "cap = " << std::hex << cap;
152                         unsigned *dest   = _irqbits;
153                         dest            += cap / (sizeof(*dest) * 8);
154                         cap             &= sizeof(*dest) * 8 - 1;
155                         return *dest & (1 << cap);
156                 }
157 };
158
159 }
160
161 extern Romain::Factory theObjectFactory;