README.rst
1.. _dining-philosophers-sample:
2
3Dining Philosophers
4###################
5
6Overview
7********
8
9An implementation of a solution to the Dining Philosophers problem (a classic
10multi-thread synchronization problem). This particular implementation
11demonstrates the usage of multiple preemptible and cooperative threads of
12differing priorities, as well as dynamic mutexes and thread sleeping.
13
14The philosopher always tries to get the lowest fork first (f1 then f2). When
15done, he will give back the forks in the reverse order (f2 then f1). If he
16gets two forks, he is EATING. Otherwise, he is THINKING. Transitional states
17are shown as well, such as STARVING when the philosopher is hungry but the
18forks are not available, and HOLDING ONE FORK when a philosopher is waiting
19for the second fork to be available.
20
21Each Philosopher will randomly alternate between the EATING and THINKING state.
22
23It is possible to run the demo in coop-only or preempt-only mode. To achieve
24this, set these values for CONFIG_NUM_COOP_PRIORITIES and
25CONFIG_NUM_PREEMPT_PRIORITIES in prj.conf:
26
27preempt-only:
28
29 CONFIG_NUM_PREEMPT_PRIORITIES 6
30 CONFIG_NUM_COOP_PRIORITIES 0
31
32coop-only:
33
34 CONFIG_NUM_PREEMPT_PRIORITIES 0
35 CONFIG_NUM_COOP_PRIORITIES 6
36
37In these cases, the philosopher threads will run with priorities 0 to 5
38(preempt-only) and -7 to -2 (coop-only).
39
40Building and Running
41********************
42
43This project outputs to the console. It can be built and executed
44on QEMU as follows:
45
46.. zephyr-app-commands::
47 :zephyr-app: samples/philosophers
48 :host-os: unix
49 :board: qemu_x86
50 :goals: run
51 :compact:
52
53Sample Output
54=============
55
56.. code-block:: console
57
58 Philosopher 0 [P: 3] HOLDING ONE FORK
59 Philosopher 1 [P: 2] HOLDING ONE FORK
60 Philosopher 2 [P: 1] EATING [ 1900 ms ]
61 Philosopher 3 [P: 0] THINKING [ 2500 ms ]
62 Philosopher 4 [C:-1] THINKING [ 2200 ms ]
63 Philosopher 5 [C:-2] THINKING [ 1700 ms ]
64
65Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
66
67Debug Threads
68*************
69
70The philosophers sample by default enables :kconfig:option:`CONFIG_DEBUG_THREAD_INFO`.
71This allows tools like OpenOCD and J-link to inspect thread data using
72``info threads``.
73
74.. zephyr-app-commands::
75 :zephyr-app: samples/philosophers
76 :host-os: unix
77 :board: <board_name>
78 :goals: debug
79 :compact:
80
81
82OpenOCD Sample Output
83=====================
84
85.. code-block:: console
86
87 Thread 1 received signal SIGINT, Interrupt.
88 [Switching to Thread 537003160]
89 arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107
90 107 cpsie i
91 (gdb) i threads
92 Id Target Id Frame
93 * 1 Thread 537003160 (Name: idle 00, prio:40,useropts:1) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107
94 Info : Getting thread 537002984 reg list
95 2 Thread 537002984 (Name: Philosopher 5, prio:-2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
96 Info : Getting thread 537002808 reg list
97 3 Thread 537002808 (Name: Philosopher 4, prio:-1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
98 Info : Getting thread 537002632 reg list
99 4 Thread 537002632 (Name: Philosopher 3, prio:0,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
100 Info : Getting thread 537002456 reg list
101 5 Thread 537002456 (Name: Philosopher 2, prio:1,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
102 Info : Getting thread 537002280 reg list
103 6 Thread 537002280 (Name: Philosopher 1, prio:2,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
104 Info : Getting thread 537002104 reg list
105 7 Thread 537002104 (Name: Philosopher 0, prio:3,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/aarch32/asm_inline_gcc.h:95
106
107.. code-block:: console
108
109 Philosopher 0 [P: 3] STARVING
110 Philosopher 1 [P: 2] HOLDING ONE FORK
111 Philosopher 2 [P: 1] EATING [ 400 ms ]
112 Philosopher 3 [P: 0] THINKING [ 525 ms ]
113 Philosopher 4 [C:-1] HOLDING ONE FORK
114 Philosopher 5 [C:-2] EATING [ 625 ms ]
115
116
117J-Link Sample Output
118====================
119
120.. code-block:: console
121
122 Thread 2 received signal SIGTRAP, Trace/breakpoint trap.
123 [Switching to Thread 537920592]
124 arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107
125 107 cpsie i
126 (gdb) i threads
127 Id Target Id Frame
128 * 2 Thread 537920592 (idle 00 UNKNOWN PRIO 40) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/aarch32/cpu_idle.S:107
129 3 Thread 537919536 (Philosopher 0 PENDING PRIO 3) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
130 4 Thread 537919712 (Philosopher 1 SUSPENDED PRIO 2) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
131 5 Thread 537919888 (Philosopher 2 SUSPENDED PRIO 1) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
132 6 Thread 537920064 (Philosopher 3 SUSPENDED PRIO 0) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
133 7 Thread 537920240 (Philosopher 4 PENDING PRIO 255) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
134 8 Thread 537920416 (Philosopher 5 SUSPENDED PRIO 254) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/aarch32/swap.c:53
135
136.. code-block:: console
137
138 Philosopher 0 [P: 3] STARVING
139 Philosopher 1 [P: 2] EATING [ 475 ms ]
140 Philosopher 2 [P: 1] THINKING [ 700 ms ]
141 Philosopher 3 [P: 0] THINKING [ 525 ms ]
142 Philosopher 4 [C:-1] HOLDING ONE FORK
143 Philosopher 5 [C:-2] EATING [ 625 ms ]
144