]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/manager
update
[l4.git] / l4 / pkg / plr / server / src / manager
1 // vim: ft=cpp
2
3 /*
4  * manager --
5  *
6  *     Definition of the instance manager that knows about all
7  *     redundant VCPUs as well as the fault observers.
8  *
9  * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
10  *     economic rights: Technische Universität Dresden (Germany)
11  * This file is part of TUD:OS and distributed under the terms of the
12  * GNU General Public License 2.
13  * Please see the COPYING-GPL-2 file for details.
14  */
15
16 /*
17  * Romain instance manager
18  */
19
20 #pragma once
21
22 #include "constants.h"
23 #include "app"
24 #include "thread_group.h"
25 //#include "app_loading"
26 #include "fault_observers"
27
28 #include <vector>
29 #include <cstdio>
30
31 #include "redundancy.h"
32 #include <l4/plr/measurements.h>
33
34 #if SPLIT_HANDLING
35 EXTERN_C void *split_handler_fn(void*);
36 #endif // SPLIT_HANDLING
37
38 namespace Romain
39 {
40         /*
41          * Set up and keep track of the running instances
42          */
43         class InstanceManager
44         {
45                 private:
46                         Romain::App_model *_am;
47                         std::vector<Romain::App_instance *> _instances; // instance list
48
49                         Romain::Observer *_observer_list[Romain::MAX_OBSERVERS];  // exception observer list
50                         //Romain::RedundancyCallback *_callback;                 // the callback for redundancy checking
51                         unsigned _num_observers;
52                         
53                         char const *_name;        // app name
54                         unsigned    _num_inst;    // number of instances to run
55                         l4_umword_t _num_cpu;     // number of available CPUs
56
57                         l4_addr_t _init_eip;      // initial EIP (from ELF)
58                         l4_addr_t _init_esp;      // initial ESP (from ELF)
59                         unsigned _gdt_min;        // start of GDT entries
60
61                         unsigned     _argc;       // client argc
62                         char const **_argv;       // argv of the client
63
64                         Measurements::EventBuf *_logBuf;
65
66 #if SPLIT_HANDLING
67                         pthread_t _split_handler; // resilient core handler thread
68 #endif // SPLIT_HANDLING
69
70
71                         /*
72                          * Prepare handler stack by pushing 3 values:
73                          *
74                          * 1st parameter is an app_thread
75                          * 2nd parameter is an app_instance
76                          * 3rd parameter is a dummy for the location where usually the
77                          *                  return address would be located
78                          * 4th parameter is the thread group we are dealing with
79                          */
80                         l4_addr_t prepare_stack(l4_addr_t sp, Romain::App_instance *inst,
81                                                 Romain::App_thread *thread, Romain::Thread_group* tgroup);
82
83
84                         void configure_logflags(char *flags);
85                         void configure_fault_observers();
86                         void configure_redundancy();
87                         void configure_logbuf(int size);
88
89                 public:
90                         InstanceManager(unsigned argc, char const **argv, unsigned num_instances = 1);
91
92
93                         /*
94                          * Prepare the replica instances (VCPUs)
95                          */
96                         void create_instances();
97
98                         /*
99                          * Create a single replica thread along with
100                          * its VCPU handler stack
101                          */
102                         Romain::App_thread* create_thread(l4_umword_t eip, l4_umword_t esp, unsigned inst, Romain::Thread_group *group);
103
104                         /*
105                          * Create a group of replica threads, e.g., all replicas
106                          * of a single original thread
107                          */
108                         Romain::Thread_group* create_thread_group(l4_umword_t eip, l4_umword_t esp,
109                                                                                                           std::string, unsigned cap, unsigned uid);
110
111                         /*
112                          * Setup the VCPU handler stack.
113                          *
114                          * Puts fake parameters on the handler stack so that
115                          * upon an event it looks like we got them passed as
116                          * parameters.
117                          */
118                         void prepare_handler_stack(Romain::App_thread *t, Romain::App_instance* i);
119
120                         /* 
121                          * Start the instances
122                          */
123                         void run_instances();
124
125
126                         void register_fault_observer(Romain::Observer* ob)
127                         {
128                                 _check(_num_observers >= MAX_OBSERVERS, "no more observers");
129                                 _observer_list[_num_observers++] = ob;
130                         }
131
132
133 #if 0
134                         Romain::RedundancyCallback *redundancy() const { return _callback; }
135
136
137                         void set_redundancy_callback(Romain::RedundancyCallback* cb)
138                         {
139                                 _check(_callback != 0, "there is already a callback registered?");
140                                 _callback = cb;
141                         }
142 #endif
143
144
145                         void startup_notify(Romain::App_instance *i, Romain::App_thread *t,
146                                             Romain::Thread_group* tg, Romain::App_model *a) const
147                         {
148                                 // XXX would need to be aware of observer list modifications
149                                 //     -> for now, we assume that observers are not added/removed
150                                 //        at runtime. otherwise we'd use sth. like an r/w lock with
151                                 //        reader prioritization??
152                                 for (unsigned idx = 0; idx < _num_observers; ++idx) {
153                                         DEBUG() << "[" << i->id() << "] startup notifying: " << _observer_list[idx]->name();
154                                         _observer_list[idx]->startup_notify(i,t,tg,a);
155                                 }
156                         }
157
158
159                         /*
160                          * Entry point for CPU exception handling.
161                          *
162                          * Iterates over the list of registered observers and calls
163                          * every observer's notify() function. Observers may stop
164                          * this iteration process. See Romain::Observer::ObserverReturnVal
165                          */
166                         Romain::Observer::ObserverReturnVal
167                         fault_notify(Romain::App_instance *i, Romain::App_thread *t,
168                                      Romain::Thread_group* tg, Romain::App_model *a)
169                         {
170                                 Romain::Observer::ObserverReturnVal v = Romain::Observer::Ignored;
171                                 // XXX would need to be aware of observer list modifications
172                                 //     -> for now, we assume that observers are not added/removed
173                                 //        at runtime. otherwise we'd use sth. like an r/w lock with
174                                 //        reader prioritization??
175                                 for (unsigned idx = 0; idx < _num_observers; ++idx) {
176                                         //DEBUG() << "[" << i->id() << "] notifying: " << _observer_list[idx]->name();
177                                         v = _observer_list[idx]->notify(i,t,tg,a);
178                                         switch(v) {
179                                                 case Romain::Observer::Finished:
180                                                 case Romain::Observer::Replicatable:
181                                                         //DEBUG() << "Fault handling done: " << std::hex << v;
182                                                         return v;
183                                                 default: break;
184                                         }
185                                 }
186
187                                 return v;
188                         }
189
190
191                         void query_observer_status()
192                         {
193                                 for (unsigned idx = 0; idx < _num_observers; ++idx) {
194                                         //INFO() << "querying: " << _observer_list[idx]->name();
195                                         _observer_list[idx]->status();
196                                 }
197                         }
198
199
200                         unsigned instance_count() const { return _num_inst; }
201
202                         Measurements::EventBuf* logbuf() { return _logBuf; }
203                         void logdump();
204
205                         static void VCPU_handler(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
206                         static void VCPU_startup(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
207
208
209                 private:
210                         /*
211                          * Read config from cfg file
212                          */
213                         void configure();
214         };
215 }