26 uint8_t emergency_stop;
28 uint32_t timestamp_ms;
30 uint32_t sequence_number;
38 volatile uint32_t a_ready;
39 volatile uint32_t b_ready;
40 volatile uint32_t a_compared;
41 volatile uint32_t b_compared;
42 volatile uint8_t outputs_match;
43 uint32_t mismatch_count;
45 uint32_t timestamp_ms;
48__attribute__((aligned(64)))
57 { .train_id = 101, .position = 500 },
58 { .train_id = 102, .position = 2500 },
59 { .train_id = 103, .position = 7500 },
62#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
64static uint32_t crc32(
const uint8_t *data, uint32_t len)
66 uint32_t crc = 0xffffffff;
67 for (uint32_t i = 0; i < len; i++) {
68 uint8_t
byte = data[i];
69 crc = (crc >> 8) ^ (uint32_t)(crc ^ byte);
71 return crc ^ 0xffffffff;
74static train_command_t compute_command(uint32_t train_id, uint32_t position)
80 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
84 if (position < 1000) {
87 }
else if (position < 5000) {
90 }
else if (position < 9000) {
94 cmd.emergency_stop = 1;
99 uint8_t *cmd_bytes = (uint8_t *)&cmd;
100 cmd.checksum = crc32(cmd_bytes,
sizeof(cmd) -
sizeof(cmd.checksum));
107 .train_id = train_id,
114 .sequence_number = 0,
122 uint8_t *match_status)
125 if (my_cmd->train_id == other_cmd->train_id &&
126 my_cmd->position == other_cmd->position &&
127 my_cmd->signal_state == other_cmd->signal_state &&
128 my_cmd->speed_limit == other_cmd->speed_limit) {
135 *output = safe_state(my_cmd->train_id);
140int main(
int argc,
char *argv[])
145 uint32_t cycle_count = 0;
146 uint32_t sequence = 0;
149 "┌────────────────────────────────────────────────────────┐\n");
151 "│ Process B - Cross-Comparison (Peer-to-Peer 2oo2) │\n");
153 "│ Mirrors Process A, independent comparison │\n");
155 "└────────────────────────────────────────────────────────┘\n");
156 fprintf(stderr,
"\n");
163 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
164 trains[i].position += (i + 1) * 3;
165 if (trains[i].position > 10000) {
166 trains[i].position = 10000;
170 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
175 cmd.sequence_number = sequence;
177 shared_mem.cmd_b = cmd;
178 __sync_synchronize();
179 shared_mem.b_ready = 1;
181 if (cycle_count % 10 == 0) {
183 "[WEST:B] Cycle %u: Computed train=%u, pos=%u, sig=%u, speed=%u\n",
184 cycle_count, cmd.train_id, cmd.position,
185 cmd.signal_state, cmd.speed_limit);
190 uint32_t timeout_ms = 0;
191 while (!shared_mem.a_ready && timeout_ms < 25) {
196 if (!shared_mem.a_ready) {
197 fprintf(stderr,
"[WEST:B] ERROR: Process A timeout\n");
203 uint8_t match_status;
212 shared_mem.cmd_b_out = output;
213 __sync_synchronize();
214 shared_mem.b_compared = 1;
216 if (cycle_count % 10 == 0) {
218 "[WEST:B] Received A's: train=%u, sig=%u, speed=%u\n",
219 shared_mem.cmd_a.train_id,
220 shared_mem.cmd_a.signal_state,
221 shared_mem.cmd_a.speed_limit);
224 "[WEST:B] Comparison: %s\n",
225 match_status ?
"MATCH ✓" :
"MISMATCH ✗");
228 "[WEST:B] Output: sig=%u, speed=%u\n",
229 output.signal_state, output.speed_limit);
234 while (!shared_mem.a_compared && timeout_ms < 10) {
239 if (shared_mem.a_compared) {
240 if (shared_mem.cmd_a_out.signal_state == shared_mem.cmd_b_out.signal_state &&
241 shared_mem.cmd_a_out.speed_limit == shared_mem.cmd_b_out.speed_limit) {
243 shared_mem.outputs_match = 1;
247 shared_mem.outputs_match = 0;
248 shared_mem.mismatch_count++;
251 "[WEST:B] ⚠️ ALERT: A's output differs!\n");
253 " A output: sig=%u, speed=%u\n",
254 shared_mem.cmd_a_out.signal_state,
255 shared_mem.cmd_a_out.speed_limit);
257 " B output: sig=%u, speed=%u\n",
258 shared_mem.cmd_b_out.signal_state,
259 shared_mem.cmd_b_out.speed_limit);
264 shared_mem.b_ready = 0;
265 shared_mem.b_compared = 0;