This project has been created as part of the 42 curriculum by smikhail.
Codexion is a concurrency simulation written in C, based on the famous "Dining Philosophers" problem, but adapted to the world of programming. In this scenario, a group of programmers (coders) competes for a limited resource: shared USB dongles. Each programmer needs two dongles simultaneously to compile their code. Furthermore, they must alternate between compiling, debugging, and refactoring, facing strict deadlines; otherwise, they will suffer from burnout.
The objective of this project is to manage system-level concurrency using pthreads, managing mutexes and condition variables to ensure memory protection and avoid conditions such as starvation and deadlocks.
The main innovation compared to the standard Philosophers project is the existence of two different schedulers that dictate the allocation of dongles: FIFO and EDF.
A Makefile is provided in the coders/ directory with the standard rules.
cd coders
makeThe generated executable is named codexion and takes exactly 8 arguments:
./codexion number_of_coders time_to_burnout time_to_compile time_to_debug time_to_refactor number_of_compiles_required dongle_cooldown schedulerExample execution with FIFO:
./codexion 4 410 200 200 10 5 10 fifoExample execution with EDF:
./codexion 4 410 200 200 10 5 10 edfDuring the planning and execution phases, the following potential concurrency issues and deadlocks were identified and effectively resolved:
-
Deadlocks:
- The classic circular wait problem (A waits for a resource held by B, and B waits for one held by A) was resolved by implementing an atomic, global scheduler validation logic.
- A single
arbiter_lockandarbiter_condcondition variable are used globally to evaluate if a coder can safely take both theleftandrightdongle at the same time without interrupting the queues.
-
Starvation:
- The use of a min-heap (priority queue) integrated into each dongle ensures that the allocation policy is fair and precise.
- In FIFO, requests are served strictly on a first-come, first-served basis.
- In EDF (Earliest Deadline First), coders whose burnout deadline (
time_to_burnout) is closer take priority, saving them in critical borderline cases. A coder will only take their required dongles if they are at the very top of both dongle queues.
-
Infinite thread blockages:
- If a thread suffers a burnout, the other threads could remain blocked infinitely waiting for a condition variable in the dongle request phase.
- To handle this cleanly, after a burnout, the main thread issues a global
pthread_cond_broadcastto wake up any sleeping worker threads and terminate the execution smoothly without memory leaks.
The system uses the following pthread synchronization primitives from the standard C library:
-
pthread_mutex_t:- Used in a granular way. There is one mutex for each
dongleto avoid race conditions when manipulating its metadata (owner, queue, available time). - There is a global
print_lockto serialize messages toSTDOUT. Two messages will never be mixed. - A specific
coder_lockis used for each thread to protect internal variables shared with the monitor thread (such aslast_compile_startandcompiles_done). - An
arbiter_lockacts as a master lock to safely evaluate and enforce scheduler decisions globally before taking resources.
- Used in a granular way. There is one mutex for each
-
pthread_cond_t:- An
arbiter_condcondition variable is used instead of actively waiting for a resource to be freed (Busy Waiting, which consumes excessive CPU). The programmers enter a sleeping wait state viapthread_cond_wait. - When a dongle is dropped,
pthread_cond_broadcastis called on the arbiter condition to wake up everyone. The internal scheduler then decides which thread becomes the new owner, and the chosen coder resumes execution transparently.
- An
- AI Assistance (Gemini 3.1 Pro) was used for the organization and explanation of the project, as well as the creation of the README.