samples/philosophers/README.html · samples/philosophers/README.rst 공식 원문 ↗

Zephyr 3.7.0 · Samples · Kernel · Synchronization

식사하는 철학자

Fork 획득 순서로 deadlock을 피하고 각 철학자의 실행 상태와 priority를 console과 debugger에서 관찰합니다.

Official pathsamples/philosophers/README.html
Source filesamples/philosophers/README.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

Part 1

요약·해설

고전적인 공유 자원 동기화 문제를 Zephyr thread priority와 mutex 동작으로 확인하는 sample입니다.

Threads

Preemptible · Cooperative

Sync

Dynamic mutex

Debug

OpenOCD · J-Link

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 5252FA7CB415716C994922A3FA1873DB1502C51614EB73490CBEB084130EB3B2
.. _dining-philosophers-sample:

Dining Philosophers
###################

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 ]

Part 3

한국어 전문 번역

개요

Dining Philosophers 문제는 여러 thread가 제한된 공유 자원을 함께 사용할 때 생기는 고전적인 동기화 문제입니다. 이 sample은 그 해법을 구현하면서 서로 다른 priority를 가진 여러 preemptible thread와 cooperative thread, 실행 중에 만드는 mutex, thread sleep을 함께 보여 줍니다.

각 철학자는 번호가 낮은 fork부터 가져오려고 합니다. 즉 f1을 먼저 얻은 뒤 f2를 요청하고, 식사를 마치면 반대 순서인 f2, f1 순으로 돌려줍니다. 두 fork를 모두 얻으면 EATING, 그렇지 않으면 THINKING 상태입니다. 배가 고프지만 fork를 얻지 못한 STARVING, 두 번째 fork를 기다리는 HOLDING ONE FORK 같은 전이 상태도 표시됩니다.

각 Philosopher thread는 EATING과 THINKING 상태를 무작위로 번갈아 수행합니다.

Demo를 cooperative thread만 사용하는 coop-only mode나 preemptible thread만 사용하는 preempt-only mode로 실행할 수도 있습니다. prj.conf의 CONFIG_NUM_COOP_PRIORITIES와 CONFIG_NUM_PREEMPT_PRIORITIES 값을 다음처럼 설정합니다.

preempt-only

CONFIG_NUM_PREEMPT_PRIORITIES=6
CONFIG_NUM_COOP_PRIORITIES=0

coop-only

CONFIG_NUM_PREEMPT_PRIORITIES=0
CONFIG_NUM_COOP_PRIORITIES=6

이 경우 철학자 thread의 priority는 preempt-only에서 0부터 5까지이고, coop-only에서는 -7부터 -2까지입니다.

빌드 및 실행

이 project는 console에 결과를 출력합니다. QEMU에서 다음과 같이 build하고 실행할 수 있습니다.

west build -b qemu_x86 samples/philosophers
west build -t run

출력 예

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 ]

CTRL+A를 누른 다음 x를 눌러 QEMU를 종료합니다.

Thread 디버깅

Philosophers sample은 기본적으로 CONFIG_DEBUG_THREAD_INFO를 활성화합니다. 따라서 OpenOCD나 J-Link 같은 tool에서 info threads 명령으로 thread data를 조사할 수 있습니다.

west build -b <board_name> samples/philosophers
west debug

OpenOCD 출력 예

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
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 출력 예

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
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 ]

Source

출처

영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.