1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/pipe.h" 35 #include "spdk/util.h" 36 37 struct spdk_pipe { 38 uint8_t *buf; 39 uint32_t sz; 40 41 uint32_t write; 42 uint32_t read; 43 }; 44 45 struct spdk_pipe * 46 spdk_pipe_create(void *buf, uint32_t sz) 47 { 48 struct spdk_pipe *pipe; 49 50 pipe = calloc(1, sizeof(*pipe)); 51 if (pipe == NULL) { 52 return NULL; 53 } 54 55 pipe->buf = buf; 56 pipe->sz = sz; 57 58 return pipe; 59 } 60 61 void 62 spdk_pipe_destroy(struct spdk_pipe *pipe) 63 { 64 free(pipe); 65 } 66 67 int 68 spdk_pipe_writer_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs) 69 { 70 uint32_t sz; 71 uint32_t read; 72 uint32_t write; 73 74 read = pipe->read; 75 write = pipe->write; 76 77 if (read <= write) { 78 requested_sz = spdk_min(requested_sz, ((read + pipe->sz) - write - 1)); 79 80 sz = spdk_min(requested_sz, pipe->sz - write); 81 82 if (sz == 0) { 83 iovs[0].iov_base = NULL; 84 } else { 85 iovs[0].iov_base = pipe->buf + write; 86 } 87 iovs[0].iov_len = sz; 88 89 requested_sz -= sz; 90 91 if (requested_sz > 0) { 92 sz = spdk_min(requested_sz, read); 93 94 if (sz == 0) { 95 iovs[1].iov_base = NULL; 96 } else { 97 iovs[1].iov_base = pipe->buf; 98 } 99 iovs[1].iov_len = sz; 100 } else { 101 iovs[1].iov_base = NULL; 102 iovs[1].iov_len = 0; 103 } 104 } else { 105 sz = spdk_min(requested_sz, read - write - 1); 106 107 if (sz == 0) { 108 iovs[0].iov_base = NULL; 109 } else { 110 iovs[0].iov_base = pipe->buf + write; 111 } 112 iovs[0].iov_len = sz; 113 114 iovs[1].iov_base = NULL; 115 iovs[1].iov_len = 0; 116 } 117 118 return iovs[0].iov_len + iovs[1].iov_len; 119 } 120 121 int 122 spdk_pipe_writer_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 123 { 124 uint32_t sz; 125 uint32_t read; 126 uint32_t write; 127 128 read = pipe->read; 129 write = pipe->write; 130 131 if (requested_sz > pipe->sz - 1) { 132 return -EINVAL; 133 } 134 135 if (read <= write) { 136 if (requested_sz > (read + pipe->sz) - write) { 137 return -EINVAL; 138 } 139 140 sz = spdk_min(requested_sz, pipe->sz - write); 141 142 write += sz; 143 if (write > pipe->sz - 1) { 144 write = 0; 145 } 146 requested_sz -= sz; 147 148 if (requested_sz > 0) { 149 if (requested_sz >= read) { 150 return -EINVAL; 151 } 152 153 write = requested_sz; 154 } 155 } else { 156 if (requested_sz > (read - write - 1)) { 157 return -EINVAL; 158 } 159 160 write += requested_sz; 161 } 162 163 pipe->write = write; 164 165 return 0; 166 } 167 168 uint32_t 169 spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe) 170 { 171 uint32_t read; 172 uint32_t write; 173 174 read = pipe->read; 175 write = pipe->write; 176 177 if (read <= write) { 178 return write - read; 179 } 180 181 return (write + pipe->sz) - read; 182 } 183 184 int 185 spdk_pipe_reader_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs) 186 { 187 uint32_t sz; 188 uint32_t read; 189 uint32_t write; 190 191 read = pipe->read; 192 write = pipe->write; 193 194 if (read <= write) { 195 sz = spdk_min(requested_sz, write - read); 196 197 if (sz == 0) { 198 iovs[0].iov_base = NULL; 199 } else { 200 iovs[0].iov_base = pipe->buf + read; 201 } 202 iovs[0].iov_len = sz; 203 204 iovs[1].iov_base = NULL; 205 iovs[1].iov_len = 0; 206 } else { 207 sz = spdk_min(requested_sz, pipe->sz - read); 208 209 if (sz == 0) { 210 iovs[0].iov_base = NULL; 211 } else { 212 iovs[0].iov_base = pipe->buf + read; 213 } 214 iovs[0].iov_len = sz; 215 216 requested_sz -= sz; 217 218 if (requested_sz > 0) { 219 sz = spdk_min(requested_sz, write); 220 221 if (sz == 0) { 222 iovs[1].iov_base = NULL; 223 } else { 224 iovs[1].iov_base = pipe->buf; 225 } 226 iovs[1].iov_len = sz; 227 } else { 228 iovs[1].iov_base = NULL; 229 iovs[1].iov_len = 0; 230 } 231 } 232 233 return iovs[0].iov_len + iovs[1].iov_len; 234 } 235 236 int 237 spdk_pipe_reader_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 238 { 239 uint32_t sz; 240 uint32_t read; 241 uint32_t write; 242 243 read = pipe->read; 244 write = pipe->write; 245 246 if (read <= write) { 247 if (requested_sz > (write - read)) { 248 return -EINVAL; 249 } 250 251 read += requested_sz; 252 } else { 253 sz = spdk_min(requested_sz, pipe->sz - read); 254 255 read += sz; 256 if (read > pipe->sz - 1) { 257 read = 0; 258 } 259 requested_sz -= sz; 260 261 if (requested_sz > 0) { 262 if (requested_sz > write) { 263 return -EINVAL; 264 } 265 266 read = requested_sz; 267 } 268 } 269 270 pipe->read = read; 271 272 return 0; 273 } 274