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