Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2019 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/pipe.h"
7 : : #include "spdk/util.h"
8 : : #include "spdk/queue.h"
9 : : #include "spdk/log.h"
10 : :
11 : : struct spdk_pipe_buf {
12 : : SLIST_ENTRY(spdk_pipe_buf) link;
13 : : uint32_t sz;
14 : : };
15 : :
16 : : struct spdk_pipe_group {
17 : : SLIST_HEAD(, spdk_pipe_buf) bufs;
18 : : };
19 : :
20 : : struct spdk_pipe {
21 : : uint8_t *buf;
22 : : uint32_t sz;
23 : :
24 : : uint32_t write;
25 : : uint32_t read;
26 : : bool full;
27 : :
28 : : struct spdk_pipe_group *group;
29 : : };
30 : :
31 : : struct spdk_pipe *
32 : 16864 : spdk_pipe_create(void *buf, uint32_t sz)
33 : : {
34 : : struct spdk_pipe *pipe;
35 : :
36 : 16864 : pipe = calloc(1, sizeof(*pipe));
37 [ + + ]: 16864 : if (pipe == NULL) {
38 : 0 : return NULL;
39 : : }
40 : :
41 [ + - + - ]: 16864 : pipe->buf = buf;
42 [ + - + - ]: 16864 : pipe->sz = sz;
43 : :
44 : 16864 : return pipe;
45 : 3204 : }
46 : :
47 : : void *
48 : 17394 : spdk_pipe_destroy(struct spdk_pipe *pipe)
49 : : {
50 : : void *buf;
51 : :
52 [ + + ]: 17394 : if (pipe == NULL) {
53 : 530 : return NULL;
54 : : }
55 : :
56 [ + + + - : 16864 : if (pipe->group) {
- + ]
57 [ # # # # ]: 92 : spdk_pipe_group_remove(pipe->group, pipe);
58 : 0 : }
59 : :
60 [ + - + - ]: 16864 : buf = pipe->buf;
61 : 16864 : free(pipe);
62 : 16864 : return buf;
63 : 3229 : }
64 : :
65 : : static void
66 : 13782232 : pipe_alloc_buf_from_group(struct spdk_pipe *pipe)
67 : : {
68 : : struct spdk_pipe_buf *buf;
69 : : struct spdk_pipe_group *group;
70 : :
71 [ + + + - : 13782232 : assert(pipe->group != NULL);
+ - # # ]
72 [ + - + - ]: 13782232 : group = pipe->group;
73 : :
74 : : /* We have to pick a buffer that's the correct size. It's almost always
75 : : * the first one. */
76 [ + - + - : 13782232 : buf = SLIST_FIRST(&group->bufs);
+ - ]
77 [ + - ]: 13782232 : while (buf != NULL) {
78 [ + - + - : 13782232 : if (buf->sz == pipe->sz) {
+ - + - -
+ ]
79 : : /* TODO: Could track the previous and do an SLIST_REMOVE_AFTER */
80 [ + - + - : 13782232 : SLIST_REMOVE(&pipe->group->bufs, buf, spdk_pipe_buf, link);
+ - + - +
- - + + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
81 [ + - + - ]: 13782232 : pipe->buf = (void *)buf;
82 : 13782232 : return;
83 : : }
84 [ # # # # : 0 : buf = SLIST_NEXT(buf, link);
# # ]
85 : : }
86 : : /* Should never get here. */
87 [ # # ]: 0 : assert(false);
88 : : }
89 : :
90 : : int
91 : 116996157 : spdk_pipe_writer_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs)
92 : : {
93 : : uint32_t sz;
94 : : uint32_t read;
95 : : uint32_t write;
96 : :
97 [ + - + - ]: 116996157 : read = pipe->read;
98 [ + - + - ]: 116996157 : write = pipe->write;
99 : :
100 [ + + + + : 116996157 : if (pipe->full || requested_sz == 0) {
+ + + + +
+ ]
101 [ # # # # : 400 : iovs[0].iov_base = NULL;
# # ]
102 [ # # # # : 6 : iovs[0].iov_len = 0;
# # ]
103 : 6 : return 0;
104 : : }
105 : :
106 [ + + + - : 116996151 : if (pipe->buf == NULL) {
+ + ]
107 : 13781137 : pipe_alloc_buf_from_group(pipe);
108 : 17124 : }
109 : :
110 [ + + ]: 116996151 : if (read <= write) {
111 [ + - + - : 116996145 : sz = spdk_min(requested_sz, pipe->sz - write);
+ + + - +
- ]
112 : :
113 [ + - + - : 116996145 : iovs[0].iov_base = pipe->buf + write;
+ - + - +
- + - ]
114 [ + - + - : 116996037 : iovs[0].iov_len = sz;
+ - ]
115 : :
116 : 116996037 : requested_sz -= sz;
117 : :
118 [ + + ]: 116996037 : if (requested_sz > 0) {
119 [ # # ]: 9 : sz = spdk_min(requested_sz, read);
120 : :
121 [ + + # # : 9 : iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
# # # # #
# # # ]
122 [ # # # # : 9 : iovs[1].iov_len = sz;
# # ]
123 : 0 : } else {
124 [ + - + - : 116996028 : iovs[1].iov_base = NULL;
+ - ]
125 [ + - + - : 116996028 : iovs[1].iov_len = 0;
+ - ]
126 : : }
127 : 226052 : } else {
128 [ # # ]: 6 : sz = spdk_min(requested_sz, read - write);
129 : :
130 [ # # # # : 6 : iovs[0].iov_base = pipe->buf + write;
# # # # #
# # # ]
131 [ # # # # : 6 : iovs[0].iov_len = sz;
# # ]
132 [ # # # # : 6 : iovs[1].iov_base = NULL;
# # ]
133 [ # # # # : 6 : iovs[1].iov_len = 0;
# # ]
134 : : }
135 : :
136 [ + - + - : 116996043 : return iovs[0].iov_len + iovs[1].iov_len;
+ - + - +
- + - ]
137 : 226052 : }
138 : :
139 : : int
140 : 22769605 : spdk_pipe_writer_advance(struct spdk_pipe *pipe, uint32_t requested_sz)
141 : : {
142 : : uint32_t sz;
143 : : uint32_t read;
144 : : uint32_t write;
145 : :
146 [ + - + - ]: 22769605 : read = pipe->read;
147 [ + - + - ]: 22769605 : write = pipe->write;
148 : :
149 [ + + + + : 22769605 : if (requested_sz > pipe->sz || pipe->full) {
+ + + - +
- + - -
+ ]
150 : 3 : return -EINVAL;
151 : : }
152 : :
153 [ + + ]: 22769602 : if (read <= write) {
154 [ + + + - : 22769593 : if (requested_sz > (pipe->sz - write) + read) {
- + ]
155 : 3 : return -EINVAL;
156 : : }
157 : :
158 [ + - + - : 22769590 : sz = spdk_min(requested_sz, pipe->sz - write);
+ - # # #
# ]
159 : :
160 : 22769590 : write += sz;
161 [ + + + - : 22769590 : if (write == pipe->sz) {
+ - ]
162 : 2980992 : write = 0;
163 : 0 : }
164 : 22769590 : requested_sz -= sz;
165 : :
166 [ + + ]: 22769590 : if (requested_sz > 0) {
167 : 3 : write = requested_sz;
168 : 0 : }
169 : 34266 : } else {
170 [ + + ]: 9 : if (requested_sz > (read - write)) {
171 : 6 : return -EINVAL;
172 : : }
173 : :
174 : 3 : write += requested_sz;
175 : : }
176 : :
177 [ + + ]: 22769593 : if (read == write) {
178 [ # # # # ]: 2980992 : pipe->full = true;
179 : 0 : }
180 [ + - + - ]: 22769593 : pipe->write = write;
181 : :
182 : 22769593 : return 0;
183 : 34266 : }
184 : :
185 : : uint32_t
186 : 222826256 : spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe)
187 : : {
188 : : uint32_t read;
189 : : uint32_t write;
190 : :
191 [ + - + - ]: 222826256 : read = pipe->read;
192 [ + - + - ]: 222826256 : write = pipe->write;
193 : :
194 [ + + + + : 222826256 : if (read == write && !pipe->full) {
+ - + - +
+ ]
195 : 102841915 : return 0;
196 [ + + ]: 119984341 : } else if (read < write) {
197 : 79816573 : return write - read;
198 : : } else {
199 [ # # # # ]: 40167768 : return (pipe->sz - read) + write;
200 : : }
201 : 87708 : }
202 : :
203 : : int
204 : 145898426 : spdk_pipe_reader_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs)
205 : : {
206 : : uint32_t sz;
207 : : uint32_t read;
208 : : uint32_t write;
209 : :
210 [ + - + - ]: 145898426 : read = pipe->read;
211 [ + - + - ]: 145898426 : write = pipe->write;
212 : :
213 [ + + + + : 145898426 : if ((read == write && !pipe->full) || requested_sz == 0) {
+ + + + +
+ ]
214 [ + - + - : 11287393 : iovs[0].iov_base = NULL;
+ - ]
215 [ + - + - : 11287393 : iovs[0].iov_len = 0;
+ - ]
216 [ + - + - : 11287393 : iovs[1].iov_base = NULL;
+ - ]
217 [ + - + - : 11287393 : iovs[1].iov_len = 0;
+ - ]
218 [ + + ]: 134628157 : } else if (read < write) {
219 [ - + ]: 92700464 : sz = spdk_min(requested_sz, write - read);
220 : :
221 [ + - + - : 92700464 : iovs[0].iov_base = pipe->buf + read;
+ - + - +
- + - ]
222 [ + - + - : 92700464 : iovs[0].iov_len = sz;
+ - ]
223 [ + - + - : 92700464 : iovs[1].iov_base = NULL;
+ - ]
224 [ + - + - : 92700464 : iovs[1].iov_len = 0;
+ - ]
225 : 87717 : } else {
226 [ # # # # : 41910569 : sz = spdk_min(requested_sz, pipe->sz - read);
# # # # #
# ]
227 : :
228 [ # # # # : 41910569 : iovs[0].iov_base = pipe->buf + read;
# # # # #
# # # ]
229 [ # # # # : 41910569 : iovs[0].iov_len = sz;
# # ]
230 : :
231 : 41910569 : requested_sz -= sz;
232 : :
233 [ + + ]: 41910569 : if (requested_sz > 0) {
234 [ # # ]: 38929580 : sz = spdk_min(requested_sz, write);
235 [ + + # # : 38929580 : iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
# # # # #
# # # ]
236 [ # # # # : 38929580 : iovs[1].iov_len = sz;
# # ]
237 : 0 : } else {
238 [ # # # # : 2980989 : iovs[1].iov_base = NULL;
# # ]
239 [ # # # # : 2980989 : iovs[1].iov_len = 0;
# # ]
240 : : }
241 : : }
242 : :
243 [ + - + - : 145898426 : return iovs[0].iov_len + iovs[1].iov_len;
+ - + - +
- + - ]
244 : : }
245 : :
246 : : int
247 : 134611017 : spdk_pipe_reader_advance(struct spdk_pipe *pipe, uint32_t requested_sz)
248 : : {
249 : : uint32_t sz;
250 : : uint32_t read;
251 : : uint32_t write;
252 : :
253 [ + - + - ]: 134611017 : read = pipe->read;
254 [ + - + - ]: 134611017 : write = pipe->write;
255 : :
256 [ + + ]: 134611017 : if (requested_sz == 0) {
257 : 0 : return 0;
258 : : }
259 : :
260 [ + + ]: 134611017 : if (read < write) {
261 [ + + ]: 92700457 : if (requested_sz > (write - read)) {
262 : 6 : return -EINVAL;
263 : : }
264 : :
265 : 92700451 : read += requested_sz;
266 : 87704 : } else {
267 [ # # # # : 41910560 : sz = spdk_min(requested_sz, pipe->sz - read);
# # # # #
# ]
268 : :
269 : 41910560 : read += sz;
270 [ + + # # : 41910560 : if (read == pipe->sz) {
# # ]
271 : 2980983 : read = 0;
272 : 0 : }
273 : 41910560 : requested_sz -= sz;
274 : :
275 [ + + ]: 41910560 : if (requested_sz > 0) {
276 [ - + ]: 3 : if (requested_sz > write) {
277 : 0 : return -EINVAL;
278 : : }
279 : :
280 : 3 : read = requested_sz;
281 : 0 : }
282 : : }
283 : :
284 : : /* We know we advanced at least one byte, so the pipe isn't full. */
285 [ + - + - ]: 134611011 : pipe->full = false;
286 : :
287 [ + + ]: 134611011 : if (read == write) {
288 : : /* The pipe is empty. To re-use the same memory more frequently, jump
289 : : * both pointers back to the beginning of the pipe. */
290 : 22769536 : read = 0;
291 [ + - + - ]: 22769536 : pipe->write = 0;
292 : :
293 : : /* Additionally, release the buffer to the shared pool */
294 [ + + + - : 22769536 : if (pipe->group) {
+ + ]
295 [ + - + - ]: 13770157 : struct spdk_pipe_buf *buf = (struct spdk_pipe_buf *)pipe->buf;
296 [ + - + - : 13770157 : buf->sz = pipe->sz;
+ - + - ]
297 [ + - + - : 13770157 : SLIST_INSERT_HEAD(&pipe->group->bufs, buf, link);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
298 [ + - + - ]: 13770157 : pipe->buf = NULL;
299 : 15522 : }
300 : 34267 : }
301 : :
302 [ + - + - ]: 134611011 : pipe->read = read;
303 : :
304 : 134611011 : return 0;
305 : 87704 : }
306 : :
307 : : struct spdk_pipe_group *
308 : 4702 : spdk_pipe_group_create(void)
309 : : {
310 : : struct spdk_pipe_group *group;
311 : :
312 : 4702 : group = calloc(1, sizeof(*group));
313 [ + + ]: 4702 : if (!group) {
314 : 0 : return NULL;
315 : : }
316 : :
317 [ - + - + : 4702 : SLIST_INIT(&group->bufs);
- + ]
318 : :
319 : 4702 : return group;
320 : 164 : }
321 : :
322 : : void
323 : 4702 : spdk_pipe_group_destroy(struct spdk_pipe_group *group)
324 : : {
325 [ + + + - : 4702 : if (!SLIST_EMPTY(&group->bufs)) {
+ - + - ]
326 : 0 : SPDK_ERRLOG("Destroying a pipe group that still has buffers!\n");
327 [ # # ]: 0 : assert(false);
328 : : }
329 : :
330 : 4702 : free(group);
331 : 4702 : }
332 : :
333 : : int
334 : 12075 : spdk_pipe_group_add(struct spdk_pipe_group *group, struct spdk_pipe *pipe)
335 : : {
336 : : struct spdk_pipe_buf *buf;
337 : :
338 [ + + + - : 12075 : assert(pipe->group == NULL);
+ - # # ]
339 : :
340 [ + - + - ]: 12075 : pipe->group = group;
341 [ + - + + : 12075 : if (pipe->read != pipe->write || pipe->full) {
+ + + - +
- + - + -
+ - - + ]
342 : : /* Pipe currently has valid data, so keep the buffer attached
343 : : * to the pipe for now. We can move it to the group's SLIST
344 : : * later when it gets emptied.
345 : : */
346 : 0 : return 0;
347 : : }
348 : :
349 [ + - + - ]: 12075 : buf = (struct spdk_pipe_buf *)pipe->buf;
350 [ + - + - : 12075 : buf->sz = pipe->sz;
+ - + - ]
351 [ + - + - : 12075 : SLIST_INSERT_HEAD(&group->bufs, buf, link);
+ - + - +
- + - + -
+ - + - ]
352 [ + - + - ]: 12075 : pipe->buf = NULL;
353 : 12075 : return 0;
354 : 1602 : }
355 : :
356 : : int
357 : 12075 : spdk_pipe_group_remove(struct spdk_pipe_group *group, struct spdk_pipe *pipe)
358 : : {
359 [ + + + - : 12075 : assert(pipe->group == group);
+ - # # ]
360 : :
361 [ + + + - : 12075 : if (pipe->buf == NULL) {
+ - ]
362 : : /* Associate a buffer with the pipe before returning. */
363 : 1095 : pipe_alloc_buf_from_group(pipe);
364 [ - + # # : 1095 : assert(pipe->buf != NULL);
# # # # ]
365 : 0 : }
366 : :
367 [ + - + - ]: 12075 : pipe->group = NULL;
368 : 12075 : return 0;
369 : : }
|