1.. zephyr:code-sample:: dining-philosophers
2  :name: Dining Philosophers
3  :relevant-api: semaphore_apis mutex_apis stack_apis thread_apis fifo_apis lifo_apis
4
5  Implement a solution to the Dining Philosophers problem using Zephyr kernel services.
6
7Overview
8********
9
10An implementation of a solution to the Dining Philosophers problem (a classic multi-thread
11synchronization problem).  This particular implementation demonstrates the usage of multiple
12preemptible and cooperative threads of differing priorities, as well as dynamic mutexes and thread
13sleeping.
14
15The philosopher always tries to get the lowest fork first (f1 then f2).  When done, he will give
16back the forks in the reverse order (f2 then f1).  If he gets two forks, he is ``EATING``.
17Otherwise, he is ``THINKING``. Transitional states are shown as well, such as ``STARVING`` when the
18philosopher is hungry but the forks are not available, and ``HOLDING ONE FORK`` when a philosopher
19is waiting for the second fork to be available.
20
21Each Philosopher will randomly alternate between the ``EATING`` and ``THINKING`` states.
22
23It is possible to run the demo in ``coop-only`` or ``preempt-only`` mode. To achieve this, set these
24values for ``CONFIG_NUM_COOP_PRIORITIES`` and ``CONFIG_NUM_PREEMPT_PRIORITIES`` in :file:`prj.conf`:
25
26preempt-only
27  .. code-block:: cfg
28
29     CONFIG_NUM_PREEMPT_PRIORITIES=6
30     CONFIG_NUM_COOP_PRIORITIES=0
31
32
33coop-only
34  .. code-block:: cfg
35
36     CONFIG_NUM_PREEMPT_PRIORITIES=0
37     CONFIG_NUM_COOP_PRIORITIES=6
38
39In these cases, the philosopher threads will run with priorities 0 to 5 (preempt-only) and -7 to -2
40(coop-only).
41
42Building and Running
43********************
44
45This project outputs to the console.  It can be built and executed on QEMU as follows:
46
47.. zephyr-app-commands::
48   :zephyr-app: samples/philosophers
49   :host-os: unix
50   :board: qemu_x86
51   :goals: run
52   :compact:
53
54Sample Output
55=============
56
57.. code-block::
58
59   Philosopher 0 [P: 3]  HOLDING ONE FORK
60   Philosopher 1 [P: 2]  HOLDING ONE FORK
61   Philosopher 2 [P: 1]  EATING  [ 1900 ms ]
62   Philosopher 3 [P: 0]  THINKING [ 2500 ms ]
63   Philosopher 4 [C:-1]  THINKING [ 2200 ms ]
64   Philosopher 5 [C:-2]  THINKING [ 1700 ms ]
65
66Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
67
68Debug Threads
69*************
70
71The philosophers sample by default enables :kconfig:option:`CONFIG_DEBUG_THREAD_INFO`. This allows
72tools like OpenOCD and J-link to inspect thread data using ``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::
86
87   Thread 1 received signal SIGINT, Interrupt.
88   [Switching to Thread 537003160]
89   arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/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/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/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/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/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/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/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/asm_inline_gcc.h:95
106
107.. code-block::
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::
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/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/cpu_idle.S:107
129     3    Thread 537919536 (Philosopher 0 PENDING PRIO 3)     arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/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/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/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/swap.c:53
133     7    Thread 537920240 (Philosopher 4 PENDING PRIO 255)   arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/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/swap.c:53
135
136.. code-block::
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