31 uint8_t emergency_stop;
33 uint32_t timestamp_ms;
35 uint32_t sequence_number;
47 volatile uint32_t a_ready;
48 volatile uint32_t b_ready;
49 volatile uint32_t a_compared;
50 volatile uint32_t b_compared;
51 volatile uint8_t outputs_match;
52 uint32_t mismatch_count;
54 uint32_t timestamp_ms;
57__attribute__((aligned(64)))
70 { .train_id = 101, .position = 500 },
71 { .train_id = 102, .position = 2500 },
72 { .train_id = 103, .position = 7500 },
75#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
81static uint32_t crc32(
const uint8_t *data, uint32_t len)
83 uint32_t crc = 0xffffffff;
84 for (uint32_t i = 0; i < len; i++) {
85 uint8_t
byte = data[i];
86 crc = (crc >> 8) ^ (uint32_t)(crc ^ byte);
88 return crc ^ 0xffffffff;
91static train_command_t compute_command(uint32_t train_id, uint32_t position)
97 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
101 if (position < 1000) {
102 cmd.signal_state = 2;
103 cmd.speed_limit = 80;
104 }
else if (position < 5000) {
105 cmd.signal_state = 1;
106 cmd.speed_limit = 40;
107 }
else if (position < 9000) {
108 cmd.signal_state = 0;
111 cmd.emergency_stop = 1;
112 cmd.signal_state = 0;
116 uint8_t *cmd_bytes = (uint8_t *)&cmd;
117 cmd.checksum = crc32(cmd_bytes,
sizeof(cmd) -
sizeof(cmd.checksum));
128 .train_id = train_id,
135 .sequence_number = 0,
143 uint8_t *match_status)
146 if (my_cmd->train_id == other_cmd->train_id &&
147 my_cmd->position == other_cmd->position &&
148 my_cmd->signal_state == other_cmd->signal_state &&
149 my_cmd->speed_limit == other_cmd->speed_limit) {
158 *output = safe_state(my_cmd->train_id);
167int main(
int argc,
char *argv[])
172 uint32_t cycle_count = 0;
173 uint32_t sequence = 0;
176 "┌────────────────────────────────────────────────────────┐\n");
178 "│ Process A - Cross-Comparison (Peer-to-Peer 2oo2) │\n");
180 "│ Computes independently, compares with B, co-decides │\n");
182 "└────────────────────────────────────────────────────────┘\n");
183 fprintf(stderr,
"\n");
190 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
191 trains[i].position += (i + 1) * 3;
192 if (trains[i].position > 10000) {
193 trains[i].position = 10000;
197 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
202 cmd.sequence_number = sequence;
204 shared_mem.cmd_a = cmd;
205 shared_mem.sequence = sequence;
206 __sync_synchronize();
207 shared_mem.a_ready = 1;
209 if (cycle_count % 10 == 0) {
211 "[WEST:A] Cycle %u: Computed train=%u, pos=%u, sig=%u, speed=%u\n",
212 cycle_count, cmd.train_id, cmd.position,
213 cmd.signal_state, cmd.speed_limit);
218 uint32_t timeout_ms = 0;
219 while (!shared_mem.b_ready && timeout_ms < 25) {
224 if (!shared_mem.b_ready) {
225 fprintf(stderr,
"[WEST:A] ERROR: Process B timeout\n");
231 uint8_t match_status;
240 shared_mem.cmd_a_out = output;
241 __sync_synchronize();
242 shared_mem.a_compared = 1;
244 if (cycle_count % 10 == 0) {
246 "[WEST:A] Received B's: train=%u, sig=%u, speed=%u\n",
247 shared_mem.cmd_b.train_id,
248 shared_mem.cmd_b.signal_state,
249 shared_mem.cmd_b.speed_limit);
252 "[WEST:A] Comparison: %s\n",
253 match_status ?
"MATCH ✓" :
"MISMATCH ✗");
256 "[WEST:A] Output: sig=%u, speed=%u\n",
257 output.signal_state, output.speed_limit);
262 while (!shared_mem.b_compared && timeout_ms < 10) {
267 if (shared_mem.b_compared) {
268 if (shared_mem.cmd_a_out.signal_state == shared_mem.cmd_b_out.signal_state &&
269 shared_mem.cmd_a_out.speed_limit == shared_mem.cmd_b_out.speed_limit) {
271 shared_mem.outputs_match = 1;
275 shared_mem.outputs_match = 0;
276 shared_mem.mismatch_count++;
279 "[WEST:A] ⚠️ ALERT: B's output differs!\n");
281 " A output: sig=%u, speed=%u\n",
282 shared_mem.cmd_a_out.signal_state,
283 shared_mem.cmd_a_out.speed_limit);
285 " B output: sig=%u, speed=%u\n",
286 shared_mem.cmd_b_out.signal_state,
287 shared_mem.cmd_b_out.speed_limit);
292 shared_mem.a_ready = 0;
293 shared_mem.a_compared = 0;