summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authoryctct <yctct@yctct.com>2026-09-13 18:58:14 +0200
committeryctct <yctct@yctct.com>2026-09-13 18:58:14 +0200
commit47beba686ff9d2aab63738fba7176a5235703d05 (patch)
treef839ed36a9e9d4476fcdc59379b17903abfa35c8 /README.md
Add all files, first commit
Diffstat (limited to 'README.md')
-rw-r--r--README.md155
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.