1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/pipe.h" 7 #include "spdk/util.h" 8 9 struct spdk_pipe { 10 uint8_t *buf; 11 uint32_t sz; 12 13 uint32_t write; 14 uint32_t read; 15 }; 16 17 struct spdk_pipe * 18 spdk_pipe_create(void *buf, uint32_t sz) 19 { 20 struct spdk_pipe *pipe; 21 22 pipe = calloc(1, sizeof(*pipe)); 23 if (pipe == NULL) { 24 return NULL; 25 } 26 27 pipe->buf = buf; 28 pipe->sz = sz; 29 30 return pipe; 31 } 32 33 void 34 spdk_pipe_destroy(struct spdk_pipe *pipe) 35 { 36 free(pipe); 37 } 38 39 int 40 spdk_pipe_writer_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs) 41 { 42 uint32_t sz; 43 uint32_t read; 44 uint32_t write; 45 46 read = pipe->read; 47 write = pipe->write; 48 49 if (read <= write) { 50 requested_sz = spdk_min(requested_sz, ((read + pipe->sz) - write - 1)); 51 52 sz = spdk_min(requested_sz, pipe->sz - write); 53 54 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write); 55 iovs[0].iov_len = sz; 56 57 requested_sz -= sz; 58 59 if (requested_sz > 0) { 60 sz = spdk_min(requested_sz, read); 61 62 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf; 63 iovs[1].iov_len = sz; 64 } else { 65 iovs[1].iov_base = NULL; 66 iovs[1].iov_len = 0; 67 } 68 } else { 69 sz = spdk_min(requested_sz, read - write - 1); 70 71 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write); 72 iovs[0].iov_len = sz; 73 iovs[1].iov_base = NULL; 74 iovs[1].iov_len = 0; 75 } 76 77 return iovs[0].iov_len + iovs[1].iov_len; 78 } 79 80 int 81 spdk_pipe_writer_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 82 { 83 uint32_t sz; 84 uint32_t read; 85 uint32_t write; 86 87 read = pipe->read; 88 write = pipe->write; 89 90 if (requested_sz > pipe->sz - 1) { 91 return -EINVAL; 92 } 93 94 if (read <= write) { 95 if (requested_sz > (read + pipe->sz) - write) { 96 return -EINVAL; 97 } 98 99 sz = spdk_min(requested_sz, pipe->sz - write); 100 101 write += sz; 102 if (write > pipe->sz - 1) { 103 write = 0; 104 } 105 requested_sz -= sz; 106 107 if (requested_sz > 0) { 108 if (requested_sz >= read) { 109 return -EINVAL; 110 } 111 112 write = requested_sz; 113 } 114 } else { 115 if (requested_sz > (read - write - 1)) { 116 return -EINVAL; 117 } 118 119 write += requested_sz; 120 } 121 122 pipe->write = write; 123 124 return 0; 125 } 126 127 uint32_t 128 spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe) 129 { 130 uint32_t read; 131 uint32_t write; 132 133 read = pipe->read; 134 write = pipe->write; 135 136 if (read <= write) { 137 return write - read; 138 } 139 140 return (write + pipe->sz) - read; 141 } 142 143 int 144 spdk_pipe_reader_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs) 145 { 146 uint32_t sz; 147 uint32_t read; 148 uint32_t write; 149 150 read = pipe->read; 151 write = pipe->write; 152 153 if (read <= write) { 154 sz = spdk_min(requested_sz, write - read); 155 156 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read); 157 iovs[0].iov_len = sz; 158 iovs[1].iov_base = NULL; 159 iovs[1].iov_len = 0; 160 } else { 161 sz = spdk_min(requested_sz, pipe->sz - read); 162 163 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read); 164 iovs[0].iov_len = sz; 165 166 requested_sz -= sz; 167 168 if (requested_sz > 0) { 169 sz = spdk_min(requested_sz, write); 170 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf; 171 iovs[1].iov_len = sz; 172 } else { 173 iovs[1].iov_base = NULL; 174 iovs[1].iov_len = 0; 175 } 176 } 177 178 return iovs[0].iov_len + iovs[1].iov_len; 179 } 180 181 int 182 spdk_pipe_reader_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 183 { 184 uint32_t sz; 185 uint32_t read; 186 uint32_t write; 187 188 read = pipe->read; 189 write = pipe->write; 190 191 if (read <= write) { 192 if (requested_sz > (write - read)) { 193 return -EINVAL; 194 } 195 196 read += requested_sz; 197 } else { 198 sz = spdk_min(requested_sz, pipe->sz - read); 199 200 read += sz; 201 if (read > pipe->sz - 1) { 202 read = 0; 203 } 204 requested_sz -= sz; 205 206 if (requested_sz > 0) { 207 if (requested_sz > write) { 208 return -EINVAL; 209 } 210 211 read = requested_sz; 212 } 213 } 214 215 pipe->read = read; 216 217 return 0; 218 } 219