1.. _pipes_v2:
2
3Pipes
4#####
5
6A :dfn:`pipe` is a kernel object that allows a thread to send a byte stream
7to another thread. Pipes enable efficient inter-thread communication and can
8be used to synchronously transfer chunks of data in whole or in part.
9
10.. contents::
11    :local:
12    :depth: 2
13
14Concepts
15********
16
17Any number of pipes can be defined, limited only by available RAM. Each pipe
18is referenced by its memory address.
19
20A pipe has the following key property:
21
22* A **size** that indicates the capacity of the pipe's ring buffer. Note that a
23  size of zero defines a pipe with no ring buffer.
24
25A pipe must be initialized before it can be used. When initialized, the pipe
26is empty.
27
28Threads interact with the pipe as follows:
29
30- **Writing**: Data is synchronously written, either in whole or in part, to
31  a pipe by a thread. Accepted data is either copied directly to the waiting
32  reader(s) or to the pipe's ring buffer. If the ring buffer is full or simply
33  absent, the operation blocks until sufficient space becomes available or
34  the specified timeout expires.
35
36- **Reading**: Data is synchronously read, either in whole or in part, from a
37  pipe by a thread. Accepted data is either copied from the pipe's ring buffer
38  or directly from the waiting sender(s). If the ring buffer is empty or simply
39  absent, the operation blocks until data becomes available or the specified
40  timeout expires.
41
42- **Resetting**: A thread can reset a pipe, which resets its internal state and
43  ends all pending read and write operations with an error code.
44
45Pipes are well-suited for scenarios like producer-consumer patterns or
46streaming data between threads.
47
48Implementation
49**************
50
51A pipe is defined using a variable of type :c:struct:`k_pipe` and a
52byte buffer. The pipe must then be initialized by calling :c:func:`k_pipe_init`.
53
54The following code defines and initializes an empty pipe with a ring buffer
55capable of holding 100 bytes, aligned to a 4-byte boundary:
56
57.. code-block:: c
58
59    uint8_t __aligned(4) my_ring_buffer[100];
60    struct k_pipe my_pipe;
61
62    k_pipe_init(&my_pipe, my_ring_buffer, sizeof(my_ring_buffer));
63
64Alternatively, a pipe can be defined and initialized at compile time using
65the :c:macro:`K_PIPE_DEFINE` macro, which defines both the pipe and its
66ring buffer:
67
68.. code-block:: c
69
70    K_PIPE_DEFINE(my_pipe, 100, 4);
71
72This has the same effect as the code above.
73
74When no ring buffer is used, the buffer pointer argument should be NULL and
75the size argument should be 0.
76
77Writing to a Pipe
78=================
79
80Data is added to a pipe by calling :c:func:`k_pipe_write`.
81
82The following example demonstrates using a pipe to send data from a producer
83thread to one or more consumer threads. If the pipe's ring buffer fills up,
84the producer thread waits for a specified amount of time.
85
86.. code-block:: c
87
88   struct message_header {
89       size_t num_data_bytes; /* Example field */
90       ...
91   };
92
93   void producer_thread(void)
94   {
95       int rc;
96       uint8_t *data;
97       size_t total_size;
98       size_t bytes_written;
99
100       while (1) {
101           /* Craft message to send in the pipe */
102           make_message(data, &total_size);
103           bytes_written = 0;
104
105           /* Write data to the pipe, handling partial writes */
106           while (bytes_written < total_size) {
107               rc = k_pipe_write(&my_pipe, &data[bytes_written], total_size - bytes_written, K_NO_WAIT);
108
109               if (rc < 0) {
110                   /* Error occurred */
111                   ...
112                   break;
113               } else {
114                   /* Partial or full write succeeded; adjust for next iteration */
115                   bytes_written += rc;
116               }
117           }
118
119           /* Reset bytes_written for the next message */
120           bytes_written = 0;
121           ...
122       }
123   }
124
125Reading from a Pipe
126===================
127
128Data is retrieved from the pipe by calling :c:func:`k_pipe_read`.
129
130The following example builds on the producer thread example above. It shows
131a consumer thread that processes data generated by the producer.
132
133.. code-block:: c
134
135   struct message_header {
136       size_t num_data_bytes; /* Example field */
137       ...
138   };
139
140   void consumer_thread(void)
141   {
142       int rc;
143       uint8_t buffer[128];
144       size_t bytes_read = 0;
145       struct message_header *header = (struct message_header *)buffer;
146
147       while (1) {
148           /* Step 1: Read the message header */
149           bytes_read = 0;
150      read_header:
151           while (bytes_read < sizeof(*header)) {
152               rc = k_pipe_read(&my_pipe, &buffer[bytes_read], sizeof(*header) - bytes_read, &bytes_read, K_NO_WAIT);
153
154               if (rc < 0) {
155                   /* Error occurred */
156                   ...
157                   goto read_header;
158               }
159
160               /* Adjust for partial reads */
161               bytes_read += rc;
162           }
163
164           /* Step 2: Read the message body */
165           bytes_read = 0;
166           while (bytes_read < header->num_data_bytes) {
167               rc = k_pipe_read(&my_pipe, &buffer[sizeof(*header) + bytes_read], header->num_data_bytes - bytes_read, K_NO_WAIT);
168
169               if (rc < 0) {
170                   /* Error occurred */
171                   ...
172                   goto read_header;
173               }
174
175               /* Adjust for partial reads */
176               bytes_read += rc;
177           }
178           /* Successfully received the complete message */
179       }
180   }
181
182Resetting a Pipe
183================
184
185The pipe can be reset by calling :c:func:`k_pipe_reset`. Resetting a pipe
186resets its internal state and ends all pending operations with an error code.
187
188The following example demonstrates resetting a pipe in response to a critical
189error:
190
191.. code-block:: c
192
193    void monitor_thread(void)
194    {
195        while (1) {
196            ...
197            /* Critical error detected: reset the entire pipe to reset it. */
198            k_pipe_reset(&my_pipe);
199            ...
200        }
201    }
202
203Suggested Uses
204**************
205
206Pipes are useful for sending streams of data between threads. Typical
207applications include:
208
209- Implementing producer-consumer patterns.
210- Streaming logs or packets between threads.
211- Handling variable-length message passing in real-time systems.
212
213API Reference
214*************
215
216.. doxygengroup:: pipe_apis
217