Codexion
ProjectM3
Philosophers reborn: coders share USB dongles under pthreads with FIFO and EDF schedulers.
Requires
Unlocks
Guide
Codexion is the milestone M3 concurrency project in C, a reworked version of the classic Philosophers. Coders sit around a table and share USB dongles: each coder needs two dongles to compile, then debugs and refactors, and burns out if they wait too long between two compiles. You write the simulation with POSIX threads and mutexes, and you also choose who gets the dongles next with a scheduler (fifo or edf). It is the last C project of the core, so it is where your libft, Makefile and norminette habits are tested once more. Details below come from student repositories (Reported by students); check them against your subject.
What you will learn
- Creating, joining and synchronising threads with
pthread_create,pthread_join, mutexes and condition variables - Data races, deadlocks and starvation, and how to prove your program avoids them
- Precise timing with
gettimeofdayand shortusleeploops - Scheduling policies: first in, first out and earliest deadline first
- A min-heap or priority queue in C
- Debugging concurrency with
valgrind --tool=helgrindand-fsanitize=thread
Before you start
- Previous nodes: the M2 projects (push_swap, Python Modules, A-Maze-ing, Exam Rank 02). Your Libft and Makefile from M0 and M1 come back here, since Codexion is C.
- Tools:
ccwith-pthread,make,norminette,valgrindwith helgrind. - Reported arguments, in order: number of coders, time to burnout, time to compile, time to debug, time to refactor, number of compiles required, dongle cooldown, and the scheduler (
fifooredf). Times are in milliseconds.
Plan of attack
- Day 1: parse and validate the eight arguments. Reject negatives, non-numbers and an unknown scheduler.
- Day 1: model the table: an array of coders (thread, last compile start, compile count) and an array of dongles (mutex, release time for the cooldown).
- Day 2: one thread per coder running compile, debug, refactor in a loop. One mutex protects logging so lines never interleave.
- Day 2: a monitor that checks every millisecond or so whether a coder passed their burnout time, prints the burnout line once, and stops everyone.
- Day 3: the dongle arbiter. Grant both dongles at once or none, which removes the classic deadlock. Respect the cooldown after a release.
- Day 3: schedulers.
fifoserves requests by arrival;edfserves the coder whose burnout deadline (last compile start plus time to burnout) is closest, ties broken by arrival. A small min-heap keeps this efficient. - Day 4: edge cases: one coder (only one dongle, must burn out), cooldown zero, very short and very long times, required compiles reached.
- Day 5: run each scenario dozens of times, then helgrind and leak checks. Join every thread and destroy every mutex on every exit path.
./codexion 5 800 200 100 100 7 50 edf
./codexion 1 400 200 100 100 3 0 fifo
valgrind --tool=helgrind ./codexion 4 410 200 100 100 5 10 fifo
Common pitfalls
- Reading shared state (last compile time, stop flag) without a mutex: a data race even if it "works".
- Printing after a burnout, or printing the burnout more than about 10 ms late (reported limit).
- Deadlock when every coder holds one dongle and waits for the other.
- Starvation under
fifowhen the same coder keeps winning. - Busy waiting with no sleep that pins the CPU and skews timings.
- Global variables, leaks, or threads not joined on error.
- Norm errors in the scheduler code, which tends to grow long functions.
How it is evaluated
- Peer evaluation. The evaluator checks norminette, the Makefile, and that there are no globals.
- Scenarios where nobody should burn out are run many times; one false burnout fails.
- Scenarios where a coder must burn out check the timing of the message.
- The evaluator asks about mutexes, condition variables, deadlock avoidance and your scheduler choice, and may run helgrind.
- The README, including the AI usage section, is reviewed (Reported by students).