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

Zephyr 3.7.0 · Kernel · Services

Polling API

한 thread가 semaphore·FIFO·message queue·pipe·signal 조건을 동시에 기다립니다.

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

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

Part 1

요약·해설

Notify-only 의미, event array 수명주기, signal 동기화 위험과 7개 code example을 설명합니다.

Conditions

5 event types

Mode

notify only

Signal

one waiter · result

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 1868548911849AB6F029AA62B549A2118AE572343C0D7419BC95B6BFBA844964
.. _polling_v2:

Polling API
###########

The polling API is used to wait concurrently for any one of multiple conditions
to be fulfilled.

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

Concepts
********

The polling API's main function is :c:func:`k_poll`, which is very similar
in concept to the POSIX :c:func:`poll` function, except that it operates on
kernel objects rather than on file descriptors.

The polling API allows a single thread to wait concurrently for one or more
conditions to be fulfilled without actively looking at each one individually.

There is a limited set of such conditions:

- a semaphore becomes available
- a kernel FIFO contains data ready to be retrieved
- a kernel message queue contains data ready to be retrieved
- a kernel pipe contains data ready to be retrieved
- a poll signal is raised

A thread that wants to wait on multiple conditions must define an array of
**poll events**, one for each condition.

All events in the array must be initialized before the array can be polled on.

Each event must specify which **type** of condition must be satisfied so that
its state is changed to signal the requested condition has been met.

Each event must specify what **kernel object** it wants the condition to be
satisfied.

Each event must specify which **mode** of operation is used when the condition
is satisfied.

Each event can optionally specify a **tag** to group multiple events together,
to the user's discretion.

Apart from the kernel objects, there is also a **poll signal** pseudo-object
type that be directly signaled.

The :c:func:`k_poll` function returns as soon as one of the conditions it
is waiting for is fulfilled. It is possible for more than one to be fulfilled
when :c:func:`k_poll` returns, if they were fulfilled before
:c:func:`k_poll` was called, or due to the preemptive multi-threading
nature of the kernel. The caller must look at the state of all the poll events
in the array to figure out which ones were fulfilled and what actions to take.

Currently, there is only one mode of operation available: the object is not
acquired. As an example, this means that when :c:func:`k_poll` returns and
the poll event states that the semaphore is available, the caller of
:c:func:`k_poll()` must then invoke :c:func:`k_sem_take` to take
ownership of the semaphore. If the semaphore is contested, there is no
guarantee that it will be still available when :c:func:`k_sem_take` is
called.

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

Using k_poll()
==============

The main API is :c:func:`k_poll`, which operates on an array of poll events
of type :c:struct:`k_poll_event`. Each entry in the array represents one
event a call to :c:func:`k_poll` will wait for its condition to be
fulfilled.

Poll events can be initialized using either the runtime initializers
:c:macro:`K_POLL_EVENT_INITIALIZER()` or :c:func:`k_poll_event_init`, or
the static initializer :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER()`. An object
that matches the **type** specified must be passed to the initializers. The
**mode** *must* be set to :c:enumerator:`K_POLL_MODE_NOTIFY_ONLY`. The state
*must* be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care
of this). The user **tag** is optional and completely opaque to the API: it is
there to help a user to group similar events together. Being optional, it is
passed to the static initializer, but not the runtime ones for performance
reasons. If using runtime initializers, the user must set it separately in the
:c:struct:`k_poll_event` data structure. If an event in the array is to be
ignored, most likely temporarily, its type can be set to
:c:macro:`K_POLL_TYPE_IGNORE`.

.. code-block:: c

    struct k_poll_event events[4] = {
        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
                                        K_POLL_MODE_NOTIFY_ONLY,
                                        &my_sem, 0),
        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
                                        K_POLL_MODE_NOTIFY_ONLY,
                                        &my_fifo, 0),
        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
                                        K_POLL_MODE_NOTIFY_ONLY,
                                        &my_msgq, 0),
        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_PIPE_DATA_AVAILABLE,
                                        K_POLL_MODE_NOTIFY_ONLY,
                                        &my_pipe, 0),
    };

or at runtime

.. code-block:: c

    struct k_poll_event events[4];
    void some_init(void)
    {
        k_poll_event_init(&events[0],
                          K_POLL_TYPE_SEM_AVAILABLE,
                          K_POLL_MODE_NOTIFY_ONLY,
                          &my_sem);

        k_poll_event_init(&events[1],
                          K_POLL_TYPE_FIFO_DATA_AVAILABLE,
                          K_POLL_MODE_NOTIFY_ONLY,
                          &my_fifo);

        k_poll_event_init(&events[2],
                          K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
                          K_POLL_MODE_NOTIFY_ONLY,
                          &my_msgq);

        k_poll_event_init(&events[3],
                          K_POLL_TYPE_PIPE_DATA_AVAILABLE,
                          K_POLL_MODE_NOTIFY_ONLY,
                          &my_pipe);

        // tags are left uninitialized if unused
    }


After the events are initialized, the array can be passed to
:c:func:`k_poll`. A timeout can be specified to wait only for a specified
amount of time, or the special values :c:macro:`K_NO_WAIT` and
:c:macro:`K_FOREVER` to either not wait or wait until an event condition is
satisfied and not sooner.

A list of pollers is offered on each semaphore or FIFO and as many events
can wait in it as the app wants.
Notice that the waiters will be served in first-come-first-serve order,
not in priority order.

In case of success, :c:func:`k_poll` returns 0. If it times out, it returns
-:c:macro:`EAGAIN`.

.. code-block:: c

    // assume there is no contention on this semaphore and FIFO
    // -EADDRINUSE will not occur; the semaphore and/or data will be available

    void do_stuff(void)
    {
        rc = k_poll(events, ARRAY_SIZE(events), K_MSEC(1000));
        if (rc == 0) {
            if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
                k_sem_take(events[0].sem, 0);
            } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
                data = k_fifo_get(events[1].fifo, 0);
                // handle data
            } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
                ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
                // handle data
            } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
                ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
                // handle data
            }
        } else {
            // handle timeout
        }
    }

When :c:func:`k_poll` is called in a loop, the events state must be reset
to :c:macro:`K_POLL_STATE_NOT_READY` by the user.

.. code-block:: c

    void do_stuff(void)
    {
        for(;;) {
            rc = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
            if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
                k_sem_take(events[0].sem, 0);
            } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
                data = k_fifo_get(events[1].fifo, 0);
                // handle data
            } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
                ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
                // handle data
            } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
                ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
                // handle data
            }
            events[0].state = K_POLL_STATE_NOT_READY;
            events[1].state = K_POLL_STATE_NOT_READY;
            events[2].state = K_POLL_STATE_NOT_READY;
            events[3].state = K_POLL_STATE_NOT_READY;
        }
    }

Using k_poll_signal_raise()
===========================

One of the types of events is :c:macro:`K_POLL_TYPE_SIGNAL`: this is a "direct"
signal to a poll event. This can be seen as a lightweight binary semaphore only
one thread can wait for.

A poll signal is a separate object of type :c:struct:`k_poll_signal` that
must be attached to a k_poll_event, similar to a semaphore or FIFO. It must
first be initialized either via :c:macro:`K_POLL_SIGNAL_INITIALIZER()` or
:c:func:`k_poll_signal_init`.

.. code-block:: c

    struct k_poll_signal signal;
    void do_stuff(void)
    {
        k_poll_signal_init(&signal);
    }

It is signaled via the :c:func:`k_poll_signal_raise` function. This function
takes a user **result** parameter that is opaque to the API and can be used to
pass extra information to the thread waiting on the event.

.. code-block:: c

    struct k_poll_signal signal;

    // thread A
    void do_stuff(void)
    {
        k_poll_signal_init(&signal);

        struct k_poll_event events[1] = {
            K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
                                     K_POLL_MODE_NOTIFY_ONLY,
                                     &signal),
        };

        k_poll(events, 1, K_FOREVER);

        int signaled, result;

        k_poll_signal_check(&signal, &signaled, &result);

        if (signaled && (result == 0x1337)) {
            // A-OK!
        } else {
            // weird error
        }
    }

    // thread B
    void signal_do_stuff(void)
    {
        k_poll_signal_raise(&signal, 0x1337);
    }

If the signal is to be polled in a loop, *both* its event state must be
reset to :c:macro:`K_POLL_STATE_NOT_READY` *and* its ``result`` must be
reset using :c:func:`k_poll_signal_reset()` on each iteration if it has
been signaled.

.. code-block:: c

    struct k_poll_signal signal;
    void do_stuff(void)
    {
        k_poll_signal_init(&signal);

        struct k_poll_event events[1] = {
            K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
                                     K_POLL_MODE_NOTIFY_ONLY,
                                     &signal),
        };

        for (;;) {
            k_poll(events, 1, K_FOREVER);

            int signaled, result;

            k_poll_signal_check(&signal, &signaled, &result);

            if (signaled && (result == 0x1337)) {
                // A-OK!
            } else {
                // weird error
            }

            k_poll_signal_reset(signal);
            events[0].state = K_POLL_STATE_NOT_READY;
        }
    }

Note that poll signals are not internally synchronized. A :c:func:`k_poll` call
that is passed a signal will return after any code in the system calls
:c:func:`k_poll_signal_raise()`.  But if the signal is being
externally managed and reset via :c:func:`k_poll_signal_init()`, it is
possible that by the time the application checks, the event state may
no longer be equal to :c:macro:`K_POLL_STATE_SIGNALED`, and a (naive)
application will miss events.  Best practice is always to reset the
signal only from within the thread invoking the :c:func:`k_poll` loop, or else
to use some other event type which tracks event counts: semaphores and
FIFOs are more error-proof in this sense because they can't "miss"
events, architecturally.

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

Use :c:func:`k_poll` to consolidate multiple threads that would be pending
on one object each, saving possibly large amounts of stack space.

Use a poll signal as a lightweight binary semaphore if only one thread pends on
it.

.. note::
    Because objects are only signaled if no other thread is waiting for them to
    become available and only one thread can poll on a specific object, polling
    is best used when objects are not subject of contention between multiple
    threads, basically when a single thread operates as a main "server" or
    "dispatcher" for multiple objects and is the only one trying to acquire
    these objects.

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

Related configuration options:

* :kconfig:option:`CONFIG_POLL`

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

.. doxygengroup:: poll_apis

Part 3

한국어 전문 번역

Polling API는 여러 condition 가운데 어느 하나가 충족될 때까지 한 thread가 동시에 기다리게 합니다.

개념

중심 함수 k_poll()은 POSIX poll()과 개념이 비슷하지만 file descriptor 대신 kernel object를 대상으로 합니다. 각 object를 능동적으로 하나씩 확인하지 않고 여러 condition을 한 번에 기다릴 수 있습니다.

지원 condition은 semaphore available, FIFO data ready, message queue data ready, pipe data ready, poll signal raised의 다섯 종류입니다.

여러 condition을 기다릴 thread는 condition마다 하나씩 k_poll_event를 만들고 array 전체를 polling 전에 초기화합니다. 각 event는 충족할 condition의 type, 대상 kernel object, 충족 시 operation mode를 지정하며 optional tag로 event를 임의 그룹화할 수 있습니다.

Kernel object 외에 직접 signal할 수 있는 pseudo-object인 poll signal도 있습니다. k_poll()은 하나가 충족되는 즉시 반환하지만 호출 전부터 여러 condition이 충족됐거나 preemptive multi-threading 중 추가 condition이 충족될 수 있으므로 caller는 array의 모든 state를 검사해야 합니다.

구현

k_poll() 사용

Poll event는 runtime initializer K_POLL_EVENT_INITIALIZER() 또는 k_poll_event_init(), static initializer K_POLL_EVENT_STATIC_INITIALIZER()로 초기화합니다. Type과 일치하는 object를 전달하고 mode는 반드시 K_POLL_MODE_NOTIFY_ONLY, 초기 state는 K_POLL_STATE_NOT_READY여야 합니다.

Tag는 API가 해석하지 않는 optional 값입니다. Static initializer에는 전달하지만 runtime initializer는 성능상 tag를 받지 않으므로 필요하면 구조체에 별도로 설정합니다. 잠시 무시할 event는 type을 K_POLL_TYPE_IGNORE로 바꿉니다.

네 event의 static 초기화 예제입니다.

struct k_poll_event events[4] = {
    K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
                                    K_POLL_MODE_NOTIFY_ONLY,
                                    &my_sem, 0),
    K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
                                    K_POLL_MODE_NOTIFY_ONLY,
                                    &my_fifo, 0),
    K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
                                    K_POLL_MODE_NOTIFY_ONLY,
                                    &my_msgq, 0),
    K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_PIPE_DATA_AVAILABLE,
                                    K_POLL_MODE_NOTIFY_ONLY,
                                    &my_pipe, 0),
};

같은 event를 runtime에 초기화하는 예제입니다. Tag를 쓰지 않으면 초기화되지 않은 채 남습니다.

struct k_poll_event events[4];
void some_init(void)
{
    k_poll_event_init(&events[0],
                      K_POLL_TYPE_SEM_AVAILABLE,
                      K_POLL_MODE_NOTIFY_ONLY,
                      &my_sem);

    k_poll_event_init(&events[1],
                      K_POLL_TYPE_FIFO_DATA_AVAILABLE,
                      K_POLL_MODE_NOTIFY_ONLY,
                      &my_fifo);

    k_poll_event_init(&events[2],
                      K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
                      K_POLL_MODE_NOTIFY_ONLY,
                      &my_msgq);

    k_poll_event_init(&events[3],
                      K_POLL_TYPE_PIPE_DATA_AVAILABLE,
                      K_POLL_MODE_NOTIFY_ONLY,
                      &my_pipe);

    // tags are left uninitialized if unused
}

초기화한 array를 k_poll()에 전달합니다. Timeout 값, K_NO_WAIT 또는 K_FOREVER를 사용할 수 있습니다. 각 semaphore나 FIFO에는 poller list가 있어 application이 원하는 수만큼 event가 기다릴 수 있지만 waiter는 priority 순서가 아니라 first-come-first-served 순서로 처리됩니다.

성공하면 0, timeout이면 -EAGAIN을 반환합니다. 다음 예제는 경합이 없어 -EADDRINUSE가 발생하지 않고 semaphore나 data가 그대로 available이라고 가정합니다.

// assume there is no contention on this semaphore and FIFO
// -EADDRINUSE will not occur; the semaphore and/or data will be available

void do_stuff(void)
{
    rc = k_poll(events, ARRAY_SIZE(events), K_MSEC(1000));
    if (rc == 0) {
        if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
            k_sem_take(events[0].sem, 0);
        } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
            data = k_fifo_get(events[1].fifo, 0);
            // handle data
        } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
            ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
            // handle data
        } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
            ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
            // handle data
        }
    } else {
        // handle timeout
    }
}

k_poll()을 loop에서 반복하면 사용자가 매 iteration마다 event state를 K_POLL_STATE_NOT_READY로 reset해야 합니다.

void do_stuff(void)
{
    for(;;) {
        rc = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
        if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
            k_sem_take(events[0].sem, 0);
        } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
            data = k_fifo_get(events[1].fifo, 0);
            // handle data
        } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
            ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
            // handle data
        } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
            ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
            // handle data
        }
        events[0].state = K_POLL_STATE_NOT_READY;
        events[1].state = K_POLL_STATE_NOT_READY;
        events[2].state = K_POLL_STATE_NOT_READY;
        events[3].state = K_POLL_STATE_NOT_READY;
    }
}

k_poll_signal_raise() 사용

K_POLL_TYPE_SIGNAL은 poll event에 직접 전달되는 signal이며 한 thread만 기다릴 수 있는 lightweight binary semaphore처럼 볼 수 있습니다. 별도 k_poll_signal object를 event에 연결하고 K_POLL_SIGNAL_INITIALIZER() 또는 k_poll_signal_init()으로 초기화합니다.

struct k_poll_signal signal;
void do_stuff(void)
{
    k_poll_signal_init(&signal);
}

k_poll_signal_raise()는 API가 해석하지 않는 user result 값을 함께 받아 waiting thread에 추가 정보를 전달할 수 있습니다.

struct k_poll_signal signal;

// thread A
void do_stuff(void)
{
    k_poll_signal_init(&signal);

    struct k_poll_event events[1] = {
        K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
                                 K_POLL_MODE_NOTIFY_ONLY,
                                 &signal),
    };

    k_poll(events, 1, K_FOREVER);

    int signaled, result;

    k_poll_signal_check(&signal, &signaled, &result);

    if (signaled && (result == 0x1337)) {
        // A-OK!
    } else {
        // weird error
    }
}

// thread B
void signal_do_stuff(void)
{
    k_poll_signal_raise(&signal, 0x1337);
}

Signal을 loop에서 poll하면 event state와 signal result를 매 iteration reset해야 합니다.

struct k_poll_signal signal;
void do_stuff(void)
{
    k_poll_signal_init(&signal);

    struct k_poll_event events[1] = {
        K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
                                 K_POLL_MODE_NOTIFY_ONLY,
                                 &signal),
    };

    for (;;) {
        k_poll(events, 1, K_FOREVER);

        int signaled, result;

        k_poll_signal_check(&signal, &signaled, &result);

        if (signaled && (result == 0x1337)) {
            // A-OK!
        } else {
            // weird error
        }

        k_poll_signal_reset(signal);
        events[0].state = K_POLL_STATE_NOT_READY;
    }
}

권장 용도

Object 하나마다 별도 thread를 대기시키는 대신 k_poll()로 통합하면 큰 stack 공간을 절약할 수 있습니다. Poll signal은 하나의 thread만 기다릴 때 lightweight binary semaphore로 사용할 수 있습니다.

설정 옵션

관련 Kconfig option은 CONFIG_POLL입니다.

API 참고: poll_apis

Defines

K_POLL_TYPE_IGNORE

이 event를 poll 대상에서 제외하는 type입니다.

K_POLL_TYPE_SIGNAL

poll signal이 raise되기를 기다리는 event type입니다.

K_POLL_TYPE_SEM_AVAILABLE

semaphore를 사용할 수 있음을 나타내는 event type입니다.

K_POLL_TYPE_DATA_AVAILABLE

호환되는 data object에 data가 있음을 나타내는 일반 type 값입니다.

K_POLL_TYPE_FIFO_DATA_AVAILABLE

kernel FIFO에 꺼낼 data가 있음을 나타내는 event type입니다.

K_POLL_TYPE_MSGQ_DATA_AVAILABLE

kernel message queue에 꺼낼 data가 있음을 나타내는 event type입니다.

K_POLL_TYPE_PIPE_DATA_AVAILABLE

kernel pipe에 읽을 data가 있음을 나타내는 event type입니다.

K_POLL_STATE_NOT_READY

요청한 condition이 아직 충족되지 않은 초기 state입니다.

K_POLL_STATE_SIGNALED

poll signal이 raise된 state입니다.

K_POLL_STATE_SEM_AVAILABLE

semaphore가 available이 된 state입니다.

K_POLL_STATE_DATA_AVAILABLE

호환되는 data object에 data가 생긴 일반 state 값입니다.

K_POLL_STATE_FIFO_DATA_AVAILABLE

FIFO data가 available인 state입니다.

K_POLL_STATE_MSGQ_DATA_AVAILABLE

message queue data가 available인 state입니다.

K_POLL_STATE_PIPE_DATA_AVAILABLE

pipe data가 available인 state입니다.

K_POLL_STATE_CANCELLED

대기 중인 poll event가 cancel된 state입니다.

K_POLL_SIGNAL_INITIALIZER(obj)

poll signal object의 static initializer입니다.

K_POLL_EVENT_INITIALIZER(_event_type, _event_mode, _event_obj)

tag 없이 poll event를 초기화하는 runtime-friendly initializer입니다.

K_POLL_EVENT_STATIC_INITIALIZER(_event_type, _event_mode, _event_obj, event_tag)

type, mode, object와 user tag를 모두 지정하는 static initializer입니다.

Enums

k_poll_modes

poll event operation mode를 정의하는 enumeration입니다.

K_POLL_MODE_NOTIFY_ONLY = 0

condition 충족 사실만 알리고 object를 자동 획득하지 않는 현재 유일한 mode입니다.

K_POLL_NUM_MODES

정의된 poll mode 수를 나타내는 sentinel 값입니다.

Functions

k_poll_event_init(event, type, mode, obj)

k_poll_event instance 하나를 초기화합니다. 호출 뒤 event array에 넣어 k_poll()에 전달할 수 있습니다.

매개변수

  • event: 초기화할 event
  • type: K_POLL_TYPE_xxx 값을 OR한 bitfield. 같은 object에 적용되는 type끼리만 결합할 수 있고 K_POLL_TYPE_IGNORE는 event를 disable함
  • mode: 향후 확장용이며 현재는 K_POLL_MODE_NOTIFY_ONLY를 사용
  • obj: kernel object 또는 poll signal
k_poll(events, num_events, timeout)

여러 poll event 중 하나 이상이 발생하기를 동시에 기다립니다. Object가 available이라는 통지는 소유권을 넘기지 않으며, object 자체에서 대기하는 일반 thread가 polling thread보다 우선합니다.

반환값이 0이면 모든 output event의 state를 검사해 필요한 동작을 수행해야 합니다. Event를 다시 사용할 때는 state를 K_POLL_STATE_NOT_READY로 reset합니다. User mode 호출은 caller resource pool에서 임시 memory allocation이 필요합니다.

매개변수

  • events: poll할 event array
  • num_events: array의 event 수
  • timeout: 대기 시간 또는 K_NO_WAIT/K_FOREVER

반환값

  • 0: 하나 이상의 event가 ready
  • -EAGAIN: 대기 시간이 만료됨
  • -EINTR: k_queue_cancel_wait() 등으로 polling이 중단됨. Output은 유효하며 cancel된 event는 K_POLL_STATE_CANCELLED
  • -ENOMEM: user mode에서 thread resource pool memory 부족
  • -EINVAL: user mode에서 잘못된 parameter
k_poll_signal_init(sig)

poll signal object를 초기화해 k_poll_signal_raise()로 signal할 수 있게 준비합니다.

매개변수

  • sig: poll signal
k_poll_signal_reset(sig)

poll signal object의 state를 unsignaled로 reset합니다.

매개변수

  • sig: poll signal object
k_poll_signal_check(sig, signaled, result)

poll signal의 signaled state와 result 값을 읽습니다.

매개변수

  • sig: poll signal object
  • signaled: signal되었으면 nonzero를 기록할 integer buffer
  • result: signal되었으면 result를 기록할 integer buffer. signal되지 않았으면 값은 undefined
k_poll_signal_raise(sig, result)

K_POLL_TYPE_SIGNAL event를 ready로 만들고 기다리던 thread를 runnable로 전환합니다. result를 저장하고 signaled field를 set하며 사용자가 reset할 때까지 유지합니다.

매개변수

  • sig: poll signal
  • result: signal result field에 저장할 값

반환값

  • 0: signal 전달 성공
  • -EAGAIN: polling thread의 timeout이 만료되는 중

Structures와 public members

k_poll_signal

Poll signal object입니다. include 경로는 kernel.h입니다.

poll_events

k_poll_signal 내부의 private sys_dlist_t member이며 사용자가 건드리면 안 됩니다.

signaled

Event가 signal되었으면 1, 아니면 0입니다. 사용자가 reset할 때까지 1을 유지합니다.

result

필요한 경우 k_poll_signal_raise()가 전달한 custom result 값입니다.

k_poll_event

Poll event 구조체이며 include 경로는 kernel.h입니다.

poller

k_poll_event 내부의 private z_poller pointer이며 사용자가 건드리면 안 됩니다.

tag

API가 해석하거나 변경하지 않는 optional user-specified tag입니다.

type

K_POLL_TYPE_xxx 값을 bitwise OR한 event type bitfield입니다.

state

K_POLL_STATE_xxx 값을 bitwise OR한 event state bitfield입니다.

mode

enum k_poll_modes에서 가져온 operation mode입니다.

unused

32-bit word 안의 사용하지 않는 bit입니다.

[anonymous]

event type별 data를 보관하는 anonymous union입니다.

Source

출처

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