diff options
| author | yctct <yctct@yctct.com> | 2026-09-13 18:58:14 +0200 |
|---|---|---|
| committer | yctct <yctct@yctct.com> | 2026-09-13 18:58:14 +0200 |
| commit | 47beba686ff9d2aab63738fba7176a5235703d05 (patch) | |
| tree | f839ed36a9e9d4476fcdc59379b17903abfa35c8 /README.md | |
Add all files, first commit
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..bff6e47 --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +# 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 +- move library headers from .h to .c files + +## 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 <https://www.gnu.org/licenses/>. + +See the file COPYING. |
