# The Dining Philosophers Problem in C ## Description This repository carries the source code of a project similar to the Dining Philosophers Problem. I wrote this program to learn about C and pthreads. There are a couple more 'features' in addition to the original requirements of the dining philosophers problem: - 'fork cooldown': a philosopher has to wait x numbers of milliseconds before she can pick up a fork - a scheduler; a heap queue with two priority methods: 'first in first out' (fifo) or 'earliest deadline first' (edf); the priority queue lives on the fork. ## Instructions To compile: $ make To run: $ ./philo number_of_philos time_to_starve time_to_eat time_to_reflect time_to_think number_of_eats_required fork_cooldown scheduler To delete ./build: $ make clean To delete ./build and the binaries: $ make fclean To delete and recompile: $ make re From the school subject: - number\_of\_philos: The number of philosophers and also the number of forks. - time\_to\_starve (in milliseconds): If a philosopher did not start eating within time\_to\_starve milliseconds since the beginning of the last time they ate or the beginning of the simulation, they starve. - time\_to\_eat (in milliseconds): The time it takes for a philosopher to eat. During that time, they must hold two forks. - time\_to\_reflect (in milliseconds): The time a philosopher will spend reflecting. - time\_to\_think (in milliseconds): The time a philosopher will spend thinking. After completing the thinking phase, the philosopher will immediately attempt to acquire forks and start eating again. - number\_of\_eats\_required: If all philosophers have eaten at least this many times, the simulation stops. Otherwise, it stops when a philosopher burns out. - fork\_cooldown (in milliseconds): After being released, a fork is unavailable until its cooldown has passed. - scheduler: The arbitration policy used by forks to decide who gets them when multiple philosophers request them. The value must be exactly one of: fifo or edf. fifo means First In, First Out: the fork is granted to the philosopher whose request arrived first. edf means Earliest Deadline First with deadline = last\_eat\_start + time\_to\_burnout. ## Resources - Advanced Programming in the UNIX Environment, third edition, W. Richard Stevens, Stephen A. Rago, Chapter 11 on pthread - on pthreads: https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html - on valgrind: https://bytes.usc.edu/cs104/wiki/valgrind/ - on valgrind: https://valgrind.org/docs/manual/mc-manual.html - on drd: https://valgrind.org/docs/manual/drd-manual.html - the man pages of pthread\_create, pthread\_mutex\_lock, pthread\_cond\_and\_wait, pthread\_join, pthread\_mutex\_destroy ## Blocking cases handled Deadlock: I use the parity solution. To prevent deadlocks, odd-numbered and even-numbered philosophers pick up their forks in different orders. Starvation prevention: whether it be with fifo or edf schedulers, a philosopher may only eat when their ticket is first in the queue. Cooldown handling: forks record the last time at which they were released. Before a philosopher checks whether their ticket is first in queue, or attempts to lock the mutex of a fork, a function computes how much time is left until a fork has cooled down, that is the waiting time. usleep() is then called with the waiting time passed as a parameter. There is also one more call of that function after a mutex is locked to deal with a hedge-case. Precise starving detection: to detect whether a philosopher has starved, a monitoring thread runs. In the routine of this thread, there is a loop calling a function check\_for\_starves which checks whether a philosopher has starves. check\_for\_starves computes that no more than the time it takes for a philosopher to burn out has elapsed since she last ate. If so, check\_for\_starves updates the value of the variable philosopher\_starved to 1. Concurrently, each time a philosopher is about to eat or each time the log is about to print, a call to the the function check\_if\_philosopher\_starved is made to check the value of philosopher\_starved. If the value is equal to 1, the threads returns and then join. Log serialization: all prints go through the function print\_log. A mutex guards access to printf(). ## Thread synchronization mechanisms The program uses pthread\_create, pthread\_join, pthread\_mutex\_init, pthread\_mutex\_lock, pthread\_mutex\_unlock, pthread\_mutex\_destroy. It creates one thread per philosopher and a monitoring thread. About thread-safety: each variable accessed throughout the program by multiple threads is protected by a mutex to prevent race conditions. ## To do, to improve - the function create\_philosopher returns a pointer to a t\_philosopher. The function could return a philosopher to reduce the number of malloc() this program uses. However, I made create\_philosopher return a pointer because I wanted to practice working with pointers. - write a unique function to free all malloc - use bzero instead of malloc to initialize all variables with 0 - think of how to refactor cooldown checks - split h file into fork.h, philos.h and sim.h ## Troubleshooting, testing Some commands I used to troubleshoot or test this program: $ strace -f ./program args $ valgrind --tool=drd ./program args $ valgrind --tool=helgrind ./pogram args # Ctrl + C and then 'thread apply all bt' in GDB when the program hangs $ echo $? to see the exit value $ addr2line -e ./codexion -f -C 0x4030F2 0x402001 $ ldd codexion to check which lib is used for compiling ## License Copyright (C) 2026 yctct This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . See the file COPYING.