1.. _fifos_v2:
2
3FIFOs
4#####
5
6A :dfn:`FIFO` is a kernel object that implements a traditional
7first in, first out (FIFO) queue, allowing threads and ISRs
8to add and remove data items of any size.
9
10.. contents::
11    :local:
12    :depth: 2
13
14Concepts
15********
16
17Any number of FIFOs can be defined (limited only by available RAM). Each FIFO is
18referenced by its memory address.
19
20A FIFO has the following key properties:
21
22* A **queue** of data items that have been added but not yet removed.
23  The queue is implemented as a simple linked list.
24
25A FIFO must be initialized before it can be used. This sets its queue to empty.
26
27FIFO data items must be aligned on a word boundary, as the kernel reserves
28the first word of an item for use as a pointer to the next data item in
29the queue. Consequently, a data item that holds N bytes of application
30data requires N+4 (or N+8) bytes of memory. There are no alignment or
31reserved space requirements for data items if they are added with
32:c:func:`k_fifo_alloc_put`, instead additional memory is temporarily
33allocated from the calling thread's resource pool.
34
35.. note::
36    FIFO data items are restricted to single active instance across all FIFO
37    data queues. Any attempt to re-add a FIFO data item to a queue before
38    it has been removed from the queue to which it was previously added will
39    result in undefined behavior.
40
41A data item may be **added** to a FIFO by a thread or an ISR.
42The item is given directly to a waiting thread, if one exists;
43otherwise the item is added to the FIFO's queue.
44There is no limit to the number of items that may be queued.
45
46A data item may be **removed** from a FIFO by a thread. If the FIFO's queue
47is empty a thread may choose to wait for a data item to be given.
48Any number of threads may wait on an empty FIFO simultaneously.
49When a data item is added, it is given to the highest priority thread
50that has waited longest.
51
52.. note::
53    The kernel does allow an ISR to remove an item from a FIFO, however
54    the ISR must not attempt to wait if the FIFO is empty.
55
56If desired, **multiple data items** can be added to a FIFO in a single operation
57if they are chained together into a singly-linked list. This capability can be
58useful if multiple writers are adding sets of related data items to the FIFO,
59as it ensures the data items in each set are not interleaved with other data
60items. Adding multiple data items to a FIFO is also more efficient than adding
61them one at a time, and can be used to guarantee that anyone who removes
62the first data item in a set will be able to remove the remaining data items
63without waiting.
64
65Implementation
66**************
67
68Defining a FIFO
69===============
70
71A FIFO is defined using a variable of type :c:struct:`k_fifo`.
72It must then be initialized by calling :c:func:`k_fifo_init`.
73
74The following code defines and initializes an empty FIFO.
75
76.. code-block:: c
77
78    struct k_fifo my_fifo;
79
80    k_fifo_init(&my_fifo);
81
82Alternatively, an empty FIFO can be defined and initialized at compile time
83by calling :c:macro:`K_FIFO_DEFINE`.
84
85The following code has the same effect as the code segment above.
86
87.. code-block:: c
88
89    K_FIFO_DEFINE(my_fifo);
90
91Writing to a FIFO
92=================
93
94A data item is added to a FIFO by calling :c:func:`k_fifo_put`.
95
96The following code builds on the example above, and uses the FIFO
97to send data to one or more consumer threads.
98
99.. code-block:: c
100
101    struct data_item_t {
102        void *fifo_reserved;   /* 1st word reserved for use by FIFO */
103        ...
104    };
105
106    struct data_item_t tx_data;
107
108    void producer_thread(int unused1, int unused2, int unused3)
109    {
110        while (1) {
111            /* create data item to send */
112            tx_data = ...
113
114            /* send data to consumers */
115            k_fifo_put(&my_fifo, &tx_data);
116
117            ...
118        }
119    }
120
121Additionally, a singly-linked list of data items can be added to a FIFO
122by calling :c:func:`k_fifo_put_list` or :c:func:`k_fifo_put_slist`.
123
124Finally, a data item can be added to a FIFO with :c:func:`k_fifo_alloc_put`.
125With this API, there is no need to reserve space for the kernel's use in
126the data item, instead additional memory will be allocated from the calling
127thread's resource pool until the item is read.
128
129Reading from a FIFO
130===================
131
132A data item is removed from a FIFO by calling :c:func:`k_fifo_get`.
133
134The following code builds on the example above, and uses the FIFO
135to obtain data items from a producer thread,
136which are then processed in some manner.
137
138.. code-block:: c
139
140    void consumer_thread(int unused1, int unused2, int unused3)
141    {
142        struct data_item_t  *rx_data;
143
144        while (1) {
145            rx_data = k_fifo_get(&my_fifo, K_FOREVER);
146
147            /* process FIFO data item */
148            ...
149        }
150    }
151
152Suggested Uses
153**************
154
155Use a FIFO to asynchronously transfer data items of arbitrary size
156in a "first in, first out" manner.
157
158Configuration Options
159*********************
160
161Related configuration options:
162
163* None
164
165API Reference
166*************
167
168.. doxygengroup:: fifo_apis
169