144 lines
6.0 KiB
ReStructuredText
144 lines
6.0 KiB
ReStructuredText
.. zephyr:code-sample:: dining-philosophers
|
|
:name: Dining Philosophers
|
|
:relevant-api: semaphore_apis mutex_apis stack_apis thread_apis fifo_apis lifo_apis
|
|
|
|
Implement a solution to the Dining Philosophers problem using Zephyr kernel services.
|
|
|
|
Overview
|
|
********
|
|
|
|
An implementation of a solution to the Dining Philosophers problem (a classic multi-thread
|
|
synchronization problem). This particular implementation demonstrates the usage of multiple
|
|
preemptible and cooperative threads of differing priorities, as well as dynamic mutexes and thread
|
|
sleeping.
|
|
|
|
The philosopher always tries to get the lowest fork first (f1 then f2). When done, he will give
|
|
back the forks in the reverse order (f2 then f1). If he gets two forks, he is ``EATING``.
|
|
Otherwise, he is ``THINKING``. Transitional states are shown as well, such as ``STARVING`` when the
|
|
philosopher is hungry but the forks are not available, and ``HOLDING ONE FORK`` when a philosopher
|
|
is waiting for the second fork to be available.
|
|
|
|
Each Philosopher will randomly alternate between the ``EATING`` and ``THINKING`` states.
|
|
|
|
It is possible to run the demo in ``coop-only`` or ``preempt-only`` mode. To achieve this, set these
|
|
values for ``CONFIG_NUM_COOP_PRIORITIES`` and ``CONFIG_NUM_PREEMPT_PRIORITIES`` in :file:`prj.conf`:
|
|
|
|
preempt-only
|
|
.. code-block:: cfg
|
|
|
|
CONFIG_NUM_PREEMPT_PRIORITIES=6
|
|
CONFIG_NUM_COOP_PRIORITIES=0
|
|
|
|
|
|
coop-only
|
|
.. code-block:: cfg
|
|
|
|
CONFIG_NUM_PREEMPT_PRIORITIES=0
|
|
CONFIG_NUM_COOP_PRIORITIES=6
|
|
|
|
In these cases, the philosopher threads will run with priorities 0 to 5 (preempt-only) and -7 to -2
|
|
(coop-only).
|
|
|
|
Building and Running
|
|
********************
|
|
|
|
This project outputs to the console. It can be built and executed on QEMU as follows:
|
|
|
|
.. zephyr-app-commands::
|
|
:zephyr-app: samples/philosophers
|
|
:host-os: unix
|
|
:board: qemu_x86
|
|
:goals: run
|
|
:compact:
|
|
|
|
Sample Output
|
|
=============
|
|
|
|
.. code-block::
|
|
|
|
Philosopher 0 [P: 3] HOLDING ONE FORK
|
|
Philosopher 1 [P: 2] HOLDING ONE FORK
|
|
Philosopher 2 [P: 1] EATING [ 1900 ms ]
|
|
Philosopher 3 [P: 0] THINKING [ 2500 ms ]
|
|
Philosopher 4 [C:-1] THINKING [ 2200 ms ]
|
|
Philosopher 5 [C:-2] THINKING [ 1700 ms ]
|
|
|
|
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.
|
|
|
|
Debug Threads
|
|
*************
|
|
|
|
The philosophers sample by default enables :kconfig:option:`CONFIG_DEBUG_THREAD_INFO`. This allows
|
|
tools like OpenOCD and J-link to inspect thread data using ``info threads``.
|
|
|
|
.. zephyr-app-commands::
|
|
:zephyr-app: samples/philosophers
|
|
:host-os: unix
|
|
:board: <board_name>
|
|
:goals: debug
|
|
:compact:
|
|
|
|
|
|
OpenOCD Sample Output
|
|
=====================
|
|
|
|
.. code-block::
|
|
|
|
Thread 1 received signal SIGINT, Interrupt.
|
|
[Switching to Thread 537003160]
|
|
arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107
|
|
107 cpsie i
|
|
(gdb) i threads
|
|
Id Target Id Frame
|
|
* 1 Thread 537003160 (Name: idle 00, prio:40,useropts:1) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107
|
|
Info : Getting thread 537002984 reg list
|
|
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
|
|
Info : Getting thread 537002808 reg list
|
|
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
|
|
Info : Getting thread 537002632 reg list
|
|
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
|
|
Info : Getting thread 537002456 reg list
|
|
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
|
|
Info : Getting thread 537002280 reg list
|
|
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
|
|
Info : Getting thread 537002104 reg list
|
|
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
|
|
|
|
.. code-block::
|
|
|
|
Philosopher 0 [P: 3] STARVING
|
|
Philosopher 1 [P: 2] HOLDING ONE FORK
|
|
Philosopher 2 [P: 1] EATING [ 400 ms ]
|
|
Philosopher 3 [P: 0] THINKING [ 525 ms ]
|
|
Philosopher 4 [C:-1] HOLDING ONE FORK
|
|
Philosopher 5 [C:-2] EATING [ 625 ms ]
|
|
|
|
|
|
J-Link Sample Output
|
|
====================
|
|
|
|
.. code-block::
|
|
|
|
Thread 2 received signal SIGTRAP, Trace/breakpoint trap.
|
|
[Switching to Thread 537920592]
|
|
arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107
|
|
107 cpsie i
|
|
(gdb) i threads
|
|
Id Target Id Frame
|
|
* 2 Thread 537920592 (idle 00 UNKNOWN PRIO 40) arch_cpu_idle () at zephyr/mainline/zephyr/arch/arm/core/cpu_idle.S:107
|
|
3 Thread 537919536 (Philosopher 0 PENDING PRIO 3) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
4 Thread 537919712 (Philosopher 1 SUSPENDED PRIO 2) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
5 Thread 537919888 (Philosopher 2 SUSPENDED PRIO 1) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
6 Thread 537920064 (Philosopher 3 SUSPENDED PRIO 0) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
7 Thread 537920240 (Philosopher 4 PENDING PRIO 255) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
8 Thread 537920416 (Philosopher 5 SUSPENDED PRIO 254) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53
|
|
|
|
.. code-block::
|
|
|
|
Philosopher 0 [P: 3] STARVING
|
|
Philosopher 1 [P: 2] EATING [ 475 ms ]
|
|
Philosopher 2 [P: 1] THINKING [ 700 ms ]
|
|
Philosopher 3 [P: 0] THINKING [ 525 ms ]
|
|
Philosopher 4 [C:-1] HOLDING ONE FORK
|
|
Philosopher 5 [C:-2] EATING [ 625 ms ]
|