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