6 * Interface for handling redundancy comparisons
8 * (c) 2011-2013 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.
16 #include "thread_group.h"
17 #include <pthread-l4.h>
28 * Register and UTCB state used for replicatable syscalls
31 char _utcb[L4_UTCB_OFFSET]; // max UTCB size
36 memset(&_regs, 0, sizeof(l4_vcpu_regs_t));
37 memset(_utcb, 0, L4_UTCB_OFFSET);
40 void put(Romain::App_thread* t);
41 void get(Romain::App_thread* t);
45 * Generic interface for a redundancy checker
47 * An object matching this interface is used by the vCPU fault handler (see
48 * server/src/handler.cc:VCPU_handler) to track redundant handler
51 class RedundancyCallback
53 Replicator _replicator;
57 Replicator& replicator() { return _replicator; }
60 * Return value from enter() call.
65 * You are the first to exec this fault handler
66 * -> for replicatable system calls this triggers the initial
67 * execution whose result is then copied to all other
72 * This tells us that we are not the initial executor of the
73 * syscall, but it is to be repeated by every replica itself.
77 * Skip the handler completely.
83 * Enter redundant handler.
85 * Determines if the handler needs to be executed.
87 virtual EnterReturnVal enter(Romain::App_instance *i, Romain::App_thread *t,
88 Romain::App_model *a) = 0;
91 * Function for the master replica to notify subsequent ones to
92 * not execute a handler, but use the master's return state (UTCB, vCPU)
95 virtual void leader_replicate(Romain::App_instance *i, Romain::App_thread *t,
96 Romain::App_model *a) = 0;
99 * Master telling the replicas to run the fault handler
102 virtual void leader_repeat(Romain::App_instance *i, Romain::App_thread *t,
103 Romain::App_model *a) = 0;
106 * Function called by each replica before resuming execution
107 * or handling of the next pending fault.
109 virtual void resume(Romain::App_instance *i, Romain::App_thread *t,
110 Romain::App_model *a) = 0;
113 * Block this replica until explicitly woken up.
115 virtual void wait(Romain::App_instance *i, Romain::App_thread *t,
116 Romain::App_model *a) = 0;
119 * Wait until all other replicas got into wait state.
121 virtual void silence(Romain::App_instance *i, Romain::App_thread *t,
122 Romain::App_model *a) = 0;
125 * Wake up all other replicas.
127 virtual void wakeup(Romain::App_instance *i, Romain::App_thread *t,
128 Romain::App_model *a) = 0;
132 class NoRed : public Romain::RedundancyCallback
135 virtual EnterReturnVal enter(Romain::App_instance *, Romain::App_thread *,
137 { return Romain::RedundancyCallback::First_syscall; }
138 virtual void leader_replicate(Romain::App_instance *, Romain::App_thread *,
139 Romain::App_model *) {}
140 virtual void leader_repeat(Romain::App_instance *, Romain::App_thread *,
141 Romain::App_model *) {}
142 virtual void resume(Romain::App_instance *, Romain::App_thread *,
143 Romain::App_model *) {}
144 virtual void wait(Romain::App_instance *i, Romain::App_thread *t,
145 Romain::App_model *a)
146 { enter_kdebug("single instances should never wait."); }
147 virtual void silence(Romain::App_instance *i, Romain::App_thread *t,
148 Romain::App_model *a) {}
149 virtual void wakeup(Romain::App_instance *i, Romain::App_thread *t,
150 Romain::App_model *a) {}
155 * N-way modular redundancy.
157 * For details on the internal protocol used, see redundancy/dmr.cc
159 class DMR : public Romain::RedundancyCallback
161 /* Replica sync points */
163 /* Sync 1: everyone waits upon entering the fault handler */
164 pthread_cond_t _enter;
165 pthread_mutex_t _enter_mtx;
166 unsigned _enter_count;
168 /* Sync 2: everyone waits before leaving the fault handler */
169 pthread_cond_t _leave;
170 pthread_mutex_t _leave_mtx;
171 unsigned _leave_count;
173 /* Sync 3: additional sync point used by the fault injection framework
174 * XXX: should this be here? */
175 pthread_cond_t _block;
176 pthread_mutex_t _block_mtx;
177 unsigned _block_count;
182 * Effective number of running instances
184 * -> this number may change at runtime (if we switch off some replicas
185 * for a while). In this case, _num_instances_bak contains the original
186 * number of instances.
188 unsigned _num_instances;
189 unsigned _num_instances_bak;
192 * List of replicas waiting to execute their fault handler
194 Romain::App_thread* _orig_vcpu[Romain::MAX_REPLICAS];
197 * Checksum all replicas, return if they match.
199 bool checksum_replicas();
202 * Recover after checksum mismatch.
204 void recover(Romain::App_model*);
208 DMR(unsigned instances);
210 virtual EnterReturnVal enter(Romain::App_instance *i, Romain::App_thread *t,
211 Romain::App_model *a);
212 virtual void leader_replicate(Romain::App_instance *i, Romain::App_thread *t,
213 Romain::App_model *a);
214 virtual void leader_repeat(Romain::App_instance *i, Romain::App_thread *t,
215 Romain::App_model *a);
216 virtual void resume(Romain::App_instance *i, Romain::App_thread *t,
217 Romain::App_model *a);
218 virtual void wait(Romain::App_instance *i, Romain::App_thread *t,
219 Romain::App_model *a);
220 virtual void silence(Romain::App_instance *i, Romain::App_thread *t,
221 Romain::App_model *a);
222 virtual void wakeup(Romain::App_instance *i, Romain::App_thread *t,
223 Romain::App_model *a);