1.. _polling_v2:
2
3Polling API
4###########
5
6The polling API is used to wait concurrently for any one of multiple conditions
7to be fulfilled.
8
9.. contents::
10    :local:
11    :depth: 2
12
13Concepts
14********
15
16The polling API's main function is :c:func:`k_poll`, which is very similar
17in concept to the POSIX :c:func:`poll` function, except that it operates on
18kernel objects rather than on file descriptors.
19
20The polling API allows a single thread to wait concurrently for one or more
21conditions to be fulfilled without actively looking at each one individually.
22
23There is a limited set of such conditions:
24
25- a semaphore becomes available
26- a kernel FIFO contains data ready to be retrieved
27- a kernel message queue contains data ready to be retrieved
28- a kernel pipe contains data ready to be retrieved
29- a poll signal is raised
30
31A thread that wants to wait on multiple conditions must define an array of
32**poll events**, one for each condition.
33
34All events in the array must be initialized before the array can be polled on.
35
36Each event must specify which **type** of condition must be satisfied so that
37its state is changed to signal the requested condition has been met.
38
39Each event must specify what **kernel object** it wants the condition to be
40satisfied.
41
42Each event must specify which **mode** of operation is used when the condition
43is satisfied.
44
45Each event can optionally specify a **tag** to group multiple events together,
46to the user's discretion.
47
48Apart from the kernel objects, there is also a **poll signal** pseudo-object
49type that be directly signaled.
50
51The :c:func:`k_poll` function returns as soon as one of the conditions it
52is waiting for is fulfilled. It is possible for more than one to be fulfilled
53when :c:func:`k_poll` returns, if they were fulfilled before
54:c:func:`k_poll` was called, or due to the preemptive multi-threading
55nature of the kernel. The caller must look at the state of all the poll events
56in the array to figure out which ones were fulfilled and what actions to take.
57
58Currently, there is only one mode of operation available: the object is not
59acquired. As an example, this means that when :c:func:`k_poll` returns and
60the poll event states that the semaphore is available, the caller of
61:c:func:`k_poll()` must then invoke :c:func:`k_sem_take` to take
62ownership of the semaphore. If the semaphore is contested, there is no
63guarantee that it will be still available when :c:func:`k_sem_take` is
64called.
65
66Implementation
67**************
68
69Using k_poll()
70==============
71
72The main API is :c:func:`k_poll`, which operates on an array of poll events
73of type :c:struct:`k_poll_event`. Each entry in the array represents one
74event a call to :c:func:`k_poll` will wait for its condition to be
75fulfilled.
76
77Poll events can be initialized using either the runtime initializers
78:c:macro:`K_POLL_EVENT_INITIALIZER()` or :c:func:`k_poll_event_init`, or
79the static initializer :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER()`. An object
80that matches the **type** specified must be passed to the initializers. The
81**mode** *must* be set to :c:enumerator:`K_POLL_MODE_NOTIFY_ONLY`. The state
82*must* be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care
83of this). The user **tag** is optional and completely opaque to the API: it is
84there to help a user to group similar events together. Being optional, it is
85passed to the static initializer, but not the runtime ones for performance
86reasons. If using runtime initializers, the user must set it separately in the
87:c:struct:`k_poll_event` data structure. If an event in the array is to be
88ignored, most likely temporarily, its type can be set to
89:c:macro:`K_POLL_TYPE_IGNORE`.
90
91.. code-block:: c
92
93    struct k_poll_event events[4] = {
94        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
95                                        K_POLL_MODE_NOTIFY_ONLY,
96                                        &my_sem, 0),
97        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
98                                        K_POLL_MODE_NOTIFY_ONLY,
99                                        &my_fifo, 0),
100        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
101                                        K_POLL_MODE_NOTIFY_ONLY,
102                                        &my_msgq, 0),
103        K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_PIPE_DATA_AVAILABLE,
104                                        K_POLL_MODE_NOTIFY_ONLY,
105                                        &my_pipe, 0),
106    };
107
108or at runtime
109
110.. code-block:: c
111
112    struct k_poll_event events[4];
113    void some_init(void)
114    {
115        k_poll_event_init(&events[0],
116                          K_POLL_TYPE_SEM_AVAILABLE,
117                          K_POLL_MODE_NOTIFY_ONLY,
118                          &my_sem);
119
120        k_poll_event_init(&events[1],
121                          K_POLL_TYPE_FIFO_DATA_AVAILABLE,
122                          K_POLL_MODE_NOTIFY_ONLY,
123                          &my_fifo);
124
125        k_poll_event_init(&events[2],
126                          K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
127                          K_POLL_MODE_NOTIFY_ONLY,
128                          &my_msgq);
129
130        k_poll_event_init(&events[3],
131                          K_POLL_TYPE_PIPE_DATA_AVAILABLE,
132                          K_POLL_MODE_NOTIFY_ONLY,
133                          &my_pipe);
134
135        // tags are left uninitialized if unused
136    }
137
138
139After the events are initialized, the array can be passed to
140:c:func:`k_poll`. A timeout can be specified to wait only for a specified
141amount of time, or the special values :c:macro:`K_NO_WAIT` and
142:c:macro:`K_FOREVER` to either not wait or wait until an event condition is
143satisfied and not sooner.
144
145A list of pollers is offered on each semaphore or FIFO and as many events
146can wait in it as the app wants.
147Notice that the waiters will be served in first-come-first-serve order,
148not in priority order.
149
150In case of success, :c:func:`k_poll` returns 0. If it times out, it returns
151-:c:macro:`EAGAIN`.
152
153.. code-block:: c
154
155    // assume there is no contention on this semaphore and FIFO
156    // -EADDRINUSE will not occur; the semaphore and/or data will be available
157
158    void do_stuff(void)
159    {
160        rc = k_poll(events, ARRAY_SIZE(events), K_MSEC(1000));
161        if (rc == 0) {
162            if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
163                k_sem_take(events[0].sem, 0);
164            } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
165                data = k_fifo_get(events[1].fifo, 0);
166                // handle data
167            } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
168                ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
169                // handle data
170            } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
171                ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
172                // handle data
173            }
174        } else {
175            // handle timeout
176        }
177    }
178
179When :c:func:`k_poll` is called in a loop, the events state must be reset
180to :c:macro:`K_POLL_STATE_NOT_READY` by the user.
181
182.. code-block:: c
183
184    void do_stuff(void)
185    {
186        for(;;) {
187            rc = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
188            if (events[0].state == K_POLL_STATE_SEM_AVAILABLE) {
189                k_sem_take(events[0].sem, 0);
190            } else if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
191                data = k_fifo_get(events[1].fifo, 0);
192                // handle data
193            } else if (events[2].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE) {
194                ret = k_msgq_get(events[2].msgq, buf, K_NO_WAIT);
195                // handle data
196            } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) {
197                ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT);
198                // handle data
199            }
200            events[0].state = K_POLL_STATE_NOT_READY;
201            events[1].state = K_POLL_STATE_NOT_READY;
202            events[2].state = K_POLL_STATE_NOT_READY;
203            events[3].state = K_POLL_STATE_NOT_READY;
204        }
205    }
206
207Using k_poll_signal_raise()
208===========================
209
210One of the types of events is :c:macro:`K_POLL_TYPE_SIGNAL`: this is a "direct"
211signal to a poll event. This can be seen as a lightweight binary semaphore only
212one thread can wait for.
213
214A poll signal is a separate object of type :c:struct:`k_poll_signal` that
215must be attached to a k_poll_event, similar to a semaphore or FIFO. It must
216first be initialized either via :c:macro:`K_POLL_SIGNAL_INITIALIZER()` or
217:c:func:`k_poll_signal_init`.
218
219.. code-block:: c
220
221    struct k_poll_signal signal;
222    void do_stuff(void)
223    {
224        k_poll_signal_init(&signal);
225    }
226
227It is signaled via the :c:func:`k_poll_signal_raise` function. This function
228takes a user **result** parameter that is opaque to the API and can be used to
229pass extra information to the thread waiting on the event.
230
231.. code-block:: c
232
233    struct k_poll_signal signal;
234
235    // thread A
236    void do_stuff(void)
237    {
238        k_poll_signal_init(&signal);
239
240        struct k_poll_event events[1] = {
241            K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
242                                     K_POLL_MODE_NOTIFY_ONLY,
243                                     &signal),
244        };
245
246        k_poll(events, 1, K_FOREVER);
247
248        int signaled, result;
249
250        k_poll_signal_check(&signal, &signaled, &result);
251
252        if (signaled && (result == 0x1337)) {
253            // A-OK!
254        } else {
255            // weird error
256        }
257    }
258
259    // thread B
260    void signal_do_stuff(void)
261    {
262        k_poll_signal_raise(&signal, 0x1337);
263    }
264
265If the signal is to be polled in a loop, *both* its event state must be
266reset to :c:macro:`K_POLL_STATE_NOT_READY` *and* its ``result`` must be
267reset using :c:func:`k_poll_signal_reset()` on each iteration if it has
268been signaled.
269
270.. code-block:: c
271
272    struct k_poll_signal signal;
273    void do_stuff(void)
274    {
275        k_poll_signal_init(&signal);
276
277        struct k_poll_event events[1] = {
278            K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
279                                     K_POLL_MODE_NOTIFY_ONLY,
280                                     &signal),
281        };
282
283        for (;;) {
284            k_poll(events, 1, K_FOREVER);
285
286            int signaled, result;
287
288            k_poll_signal_check(&signal, &signaled, &result);
289
290            if (signaled && (result == 0x1337)) {
291                // A-OK!
292            } else {
293                // weird error
294            }
295
296            k_poll_signal_reset(signal);
297            events[0].state = K_POLL_STATE_NOT_READY;
298        }
299    }
300
301Note that poll signals are not internally synchronized. A :c:func:`k_poll` call
302that is passed a signal will return after any code in the system calls
303:c:func:`k_poll_signal_raise()`.  But if the signal is being
304externally managed and reset via :c:func:`k_poll_signal_init()`, it is
305possible that by the time the application checks, the event state may
306no longer be equal to :c:macro:`K_POLL_STATE_SIGNALED`, and a (naive)
307application will miss events.  Best practice is always to reset the
308signal only from within the thread invoking the :c:func:`k_poll` loop, or else
309to use some other event type which tracks event counts: semaphores and
310FIFOs are more error-proof in this sense because they can't "miss"
311events, architecturally.
312
313Suggested Uses
314**************
315
316Use :c:func:`k_poll` to consolidate multiple threads that would be pending
317on one object each, saving possibly large amounts of stack space.
318
319Use a poll signal as a lightweight binary semaphore if only one thread pends on
320it.
321
322.. note::
323    Because objects are only signaled if no other thread is waiting for them to
324    become available and only one thread can poll on a specific object, polling
325    is best used when objects are not subject of contention between multiple
326    threads, basically when a single thread operates as a main "server" or
327    "dispatcher" for multiple objects and is the only one trying to acquire
328    these objects.
329
330Configuration Options
331*********************
332
333Related configuration options:
334
335* :kconfig:option:`CONFIG_POLL`
336
337API Reference
338*************
339
340.. doxygengroup:: poll_apis
341