Priority Inversion on Mars — Java Bug Hunt
Modelled on Mars Pathfinder (July 1997): days after landing, the spacecraft began resetting itself.
- Language: Java
- Layer: Backend
- Difficulty: Hard
- Concepts: Concurrency, State
- Modelled on: NASA Mars Pathfinder · 1997
- Visible tests: without contention the medium task simply pre-empts meteo; the bus task meets its watchdog deadline
- Reward: 50 XP for a complete fix
Briefing
Modelled on Mars Pathfinder (July 1997): days after landing, the spacecraft began resetting itself. JPL traced it to priority inversion in its VxWorks software: a low-priority meteorological task held a mutex guarding the information bus, the high-priority bus-management task blocked waiting for it, and medium-priority tasks kept pre-empting the low-priority holder. A watchdog saw that the bus task had not completed in time and reset the system. JPL fixed it by uploading a change that enabled priority inheritance on that mutex.
This project reconstructs it with a deterministic tick scheduler (Task.java, locked). BusMutex is a plain lock: a task blocked on it does nothing for the owner.
Fix BusMutex so it implements priority inheritance.
Bug report
BUG-MPF-0797 · Priority: Critical (spacecraft resets) · Reported by: flight software
Scheduler.run executes one op per tick, always picking the runnable task with the highest effectivePriority (ties: the task listed first). At the start of every tick it calls mutex.block(t) for each task waiting on the held mutex.
BusMutex must keep the public field owner and implement:
- tryLock(t): take the mutex if free (owner = t), return whether it did
- block(t): t is waiting; the owner's effectivePriority is raised to max(owner.effectivePriority, t.effectivePriority) (priority inheritance)
- unlock(t): if t owns it, release it and restore t.effectivePriority to t.basePriority
With meteo (priority 1, arrives tick 0: LOCK WORK WORK UNLOCK), bus (priority 3, tick 1: LOCK WORK UNLOCK) and comms (priority 2, tick 2: six WORK), the bus task must finish by tick 8 (Watchdog.fed(bus, 8)); the trace is meteo x4, bus x3, comms x6.
Observed: comms runs ticks 2–7 while bus waits; bus finishes at tick 12 and the watchdog resets the lander.
Logs
[vxworks] bc_dist missed deadline; bc_sched watchdog expired
[vxworks] SYSTEM RESET
[ground] reset traced to mutex held by ASI/MET taskThe code as shipped
src/rtos/BusMutex.java (editable)
class BusMutex {
Task owner;
List<Task> waiters = new ArrayList<>();
boolean tryLock(Task t) {
if (owner != null) return false;
owner = t;
waiters.remove(t);
return true;
}
void block(Task t) {
if (!waiters.contains(t)) waiters.add(t);
}
void unlock(Task t) {
if (owner == t) owner = null;
}
}
Read-only context: src/rtos/Task.java.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Java bug hunts.