kernel/services/synchronization/semaphores.html · kernel/services/synchronization/semaphores.rst 공식 원문 ↗

Zephyr 3.7.0 · Kernel · Synchronization

Semaphores

Count와 limit으로 resource 수량 또는 producer-consumer gate를 thread와 ISR 사이에 전달합니다.

Official pathkernel/services/synchronization/semaphores.html
Source filekernel/services/synchronization/semaphores.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

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

Part 1

요약·해설

Full·empty·binary semaphore, waiter 선택과 ISR의 K_NO_WAIT 제약을 설명합니다.

State

count · limit

Operations

give · take · reset

Userspace

sys_sem

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 89055BBF916C29E062B8193E70DDBDFB7C3EE5474178293224B839A73F48DA05
.. _semaphores_v2:

Semaphores
##########

A :dfn:`semaphore` is a kernel object that implements a traditional
counting semaphore.

.. contents::
    :local:
    :depth: 2

Concepts
********

Any number of semaphores can be defined (limited only by available RAM). Each
semaphore is referenced by its memory address.

A semaphore has the following key properties:

* A **count** that indicates the number of times the semaphore can be taken.
  A count of zero indicates that the semaphore is unavailable.

* A **limit** that indicates the maximum value the semaphore's count
  can reach.

A semaphore must be initialized before it can be used. Its count must be set
to a non-negative value that is less than or equal to its limit.

A semaphore may be **given** by a thread or an ISR. Giving the semaphore
increments its count, unless the count is already equal to the limit.

A semaphore may be **taken** by a thread. Taking the semaphore
decrements its count, unless the semaphore is unavailable (i.e. at zero).
When a semaphore is unavailable a thread may choose to wait for it to be given.
Any number of threads may wait on an unavailable semaphore simultaneously.
When the semaphore is given, it is taken by the highest priority thread
that has waited longest.

.. note::
    You may initialize a "full" semaphore (count equal to limit) to limit the number
    of threads able to execute the critical section at the same time. You may also
    initialize an empty semaphore (count equal to 0, with a limit greater than 0)
    to create a gate through which no waiting thread may pass until the semaphore
    is incremented. All standard use cases of the common semaphore are supported.

.. note::
    The kernel does allow an ISR to take a semaphore, however the ISR must
    not attempt to wait if the semaphore is unavailable.

Implementation
**************

Defining a Semaphore
====================

A semaphore is defined using a variable of type :c:struct:`k_sem`.
It must then be initialized by calling :c:func:`k_sem_init`.

The following code defines a semaphore, then configures it as a binary
semaphore by setting its count to 0 and its limit to 1.

.. code-block:: c

    struct k_sem my_sem;

    k_sem_init(&my_sem, 0, 1);

Alternatively, a semaphore can be defined and initialized at compile time
by calling :c:macro:`K_SEM_DEFINE`.

The following code has the same effect as the code segment above.

.. code-block:: c

    K_SEM_DEFINE(my_sem, 0, 1);

Giving a Semaphore
==================

A semaphore is given by calling :c:func:`k_sem_give`.

The following code builds on the example above, and gives the semaphore to
indicate that a unit of data is available for processing by a consumer thread.

.. code-block:: c

    void input_data_interrupt_handler(void *arg)
    {
        /* notify thread that data is available */
        k_sem_give(&my_sem);

        ...
    }

Taking a Semaphore
==================

A semaphore is taken by calling :c:func:`k_sem_take`.

The following code builds on the example above, and waits up to 50 milliseconds
for the semaphore to be given.
A warning is issued if the semaphore is not obtained in time.

.. code-block:: c

    void consumer_thread(void)
    {
        ...

        if (k_sem_take(&my_sem, K_MSEC(50)) != 0) {
            printk("Input data not available!");
        } else {
            /* fetch available data */
            ...
        }
        ...
    }

Suggested Uses
**************

Use a semaphore to control access to a set of resources by multiple threads.

Use a semaphore to synchronize processing between a producing and consuming
threads or ISRs.

Configuration Options
*********************

Related configuration options:

* None.

API Reference
**************

.. doxygengroup:: semaphore_apis

User Mode Semaphore API Reference
*********************************

The sys_sem exists in user memory working as counter semaphore for user mode
thread when user mode enabled. When user mode isn't enabled, sys_sem behaves
like k_sem.

.. doxygengroup:: user_semaphore_apis

Part 3

한국어 전문 번역

Semaphore는 traditional counting semaphore를 구현하는 kernel object입니다.

개념

RAM이 허용하는 만큼 정의하고 address로 참조합니다. Count는 앞으로 take할 수 있는 횟수이며 0이면 unavailable입니다. Limit은 count의 maximum입니다. 초기 count는 0 이상 limit 이하여야 합니다.

Thread 또는 ISR이 give하면 limit 미만에서 count가 증가합니다. Thread가 take하면 count가 감소하고 0이면 give를 기다릴 수 있습니다. 여러 waiter 중 highest-priority이면서 가장 오래 기다린 thread가 다음 take를 얻습니다.

구현

Semaphore 정의

Count 0, limit 1인 binary semaphore를 runtime에 초기화합니다.

struct k_sem my_sem;

k_sem_init(&my_sem, 0, 1);

Compile-time equivalent입니다.

K_SEM_DEFINE(my_sem, 0, 1);

Semaphore give

ISR이 consumer에게 data unit이 available임을 알립니다.

void input_data_interrupt_handler(void *arg)
{
    /* notify thread that data is available */
    k_sem_give(&my_sem);

    ...
}

Semaphore take

Consumer가 최대 50ms 기다리고 실패하면 warning을 출력합니다.

void consumer_thread(void)
{
    ...

    if (k_sem_take(&my_sem, K_MSEC(50)) != 0) {
        printk("Input data not available!");
    } else {
        /* fetch available data */
        ...
    }
    ...
}

권장 용도와 설정

여러 thread의 resource set 접근을 제한하거나 producer와 consumer thread/ISR의 처리를 동기화할 때 사용합니다. 관련 configuration option은 없습니다.

API 참고: semaphore_apis

다른 module의 semaphore declaration입니다.

extern struct k_sem <name>;
K_SEM_MAX_LIMIT

명시적 maximum 없이 counting 목적으로 쓰는 semaphore의 허용 가능한 최대 limit 값입니다.

K_SEM_DEFINE(name, initial_count, count_limit)

Semaphore를 static하게 정의하고 초기화합니다. 다른 module에서는 extern struct k_sem 으로 접근합니다.

매개변수

  • name: semaphore 이름
  • initial_count: 초기 count
  • count_limit: 최대 count
k_sem_init(sem, initial_count, limit)

첫 사용 전에 semaphore를 초기화합니다.

매개변수

  • sem: semaphore 주소
  • initial_count: 초기 count
  • limit: 최대 count

반환값

  • 0: 생성 성공
  • -EINVAL: 잘못된 값
k_sem_take(sem, timeout)

Semaphore를 take해 count를 줄입니다. ISR에서 호출할 때 timeout은 반드시 K_NO_WAIT여야 합니다.

매개변수

  • sem: semaphore 주소
  • timeout: 대기 시간 또는 K_NO_WAIT/K_FOREVER

반환값

  • 0: take 성공
  • -EBUSY: 기다리지 않고 반환
  • -EAGAIN: timeout 또는 대기 중 reset
k_sem_give(sem)

Maximum count에 도달하지 않았다면 semaphore를 give해 count를 올립니다. ISR에서도 사용할 수 있습니다.

매개변수

  • sem: semaphore 주소
k_sem_reset(sem)

Count를 0으로 만들고 outstanding take를 -EAGAIN으로 abort합니다.

매개변수

  • sem: semaphore 주소
k_sem_count_get(sem)

Current semaphore count를 반환합니다.

매개변수

  • sem: semaphore 주소

반환값

  • unsigned int: 현재 count

User mode semaphore API 참고: user_semaphore_apis

Userspace가 켜지면 sys_sem은 user memory에서 user thread용 counter semaphore로 동작하고, 꺼지면 k_sem처럼 동작합니다.

다른 module의 sys_sem declaration입니다.

extern struct sys_sem <name>;
SYS_SEM_DEFINE(_name, _initial_count, _count_limit)

User memory에 둘 수 있는 sys_sem을 static하게 정의·초기화하고 K_APP_DMEM()으로 memory domain에 배치할 수 있습니다.

매개변수

  • _name: 이름
  • _initial_count: 초기 count
  • _count_limit: 최대 count
sys_sem_init(sem, initial_count, limit)

sys_sem instance를 첫 사용 전에 초기화합니다.

매개변수

  • sem: sys_sem 주소
  • initial_count: 초기 count
  • limit: (0, INT_MAX] 범위의 최대 count

반환값

  • 0: 성공
  • -EINVAL: 잘못된 limit 또는 initial_count > limit
sys_sem_give(sem)

Maximum count 미만이면 sys_sem을 give합니다.

매개변수

  • sem: sys_sem 주소

반환값

  • 0: 성공
  • -EINVAL: 인식되지 않는 주소
  • -EACCES: 접근 권한 부족
  • -EAGAIN: 이미 maximum count
sys_sem_take(sem, timeout)

sys_sem을 take합니다.

매개변수

  • sem: sys_sem 주소
  • timeout: 대기 시간 또는 K_NO_WAIT/K_FOREVER

반환값

  • 0: 성공
  • -EINVAL: 인식되지 않는 주소
  • -ETIMEDOUT: 대기 시간 만료
  • -EACCES: 접근 권한 부족
sys_sem_count_get(sem)

Current sys_sem 값을 반환합니다.

매개변수

  • sem: sys_sem 주소

반환값

  • unsigned int: 현재 값

Source

출처

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