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 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write); 83 iovs[0].iov_len = sz; 84 85 requested_sz -= sz; 86 87 if (requested_sz > 0) { 88 sz = spdk_min(requested_sz, read); 89 90 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf; 91 iovs[1].iov_len = sz; 92 } else { 93 iovs[1].iov_base = NULL; 94 iovs[1].iov_len = 0; 95 } 96 } else { 97 sz = spdk_min(requested_sz, read - write - 1); 98 99 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + write); 100 iovs[0].iov_len = sz; 101 iovs[1].iov_base = NULL; 102 iovs[1].iov_len = 0; 103 } 104 105 return iovs[0].iov_len + iovs[1].iov_len; 106 } 107 108 int 109 spdk_pipe_writer_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 110 { 111 uint32_t sz; 112 uint32_t read; 113 uint32_t write; 114 115 read = pipe->read; 116 write = pipe->write; 117 118 if (requested_sz > pipe->sz - 1) { 119 return -EINVAL; 120 } 121 122 if (read <= write) { 123 if (requested_sz > (read + pipe->sz) - write) { 124 return -EINVAL; 125 } 126 127 sz = spdk_min(requested_sz, pipe->sz - write); 128 129 write += sz; 130 if (write > pipe->sz - 1) { 131 write = 0; 132 } 133 requested_sz -= sz; 134 135 if (requested_sz > 0) { 136 if (requested_sz >= read) { 137 return -EINVAL; 138 } 139 140 write = requested_sz; 141 } 142 } else { 143 if (requested_sz > (read - write - 1)) { 144 return -EINVAL; 145 } 146 147 write += requested_sz; 148 } 149 150 pipe->write = write; 151 152 return 0; 153 } 154 155 uint32_t 156 spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe) 157 { 158 uint32_t read; 159 uint32_t write; 160 161 read = pipe->read; 162 write = pipe->write; 163 164 if (read <= write) { 165 return write - read; 166 } 167 168 return (write + pipe->sz) - read; 169 } 170 171 int 172 spdk_pipe_reader_get_buffer(struct spdk_pipe *pipe, uint32_t requested_sz, struct iovec *iovs) 173 { 174 uint32_t sz; 175 uint32_t read; 176 uint32_t write; 177 178 read = pipe->read; 179 write = pipe->write; 180 181 if (read <= write) { 182 sz = spdk_min(requested_sz, write - read); 183 184 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read); 185 iovs[0].iov_len = sz; 186 iovs[1].iov_base = NULL; 187 iovs[1].iov_len = 0; 188 } else { 189 sz = spdk_min(requested_sz, pipe->sz - read); 190 191 iovs[0].iov_base = (sz == 0) ? NULL : (pipe->buf + read); 192 iovs[0].iov_len = sz; 193 194 requested_sz -= sz; 195 196 if (requested_sz > 0) { 197 sz = spdk_min(requested_sz, write); 198 iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf; 199 iovs[1].iov_len = sz; 200 } else { 201 iovs[1].iov_base = NULL; 202 iovs[1].iov_len = 0; 203 } 204 } 205 206 return iovs[0].iov_len + iovs[1].iov_len; 207 } 208 209 int 210 spdk_pipe_reader_advance(struct spdk_pipe *pipe, uint32_t requested_sz) 211 { 212 uint32_t sz; 213 uint32_t read; 214 uint32_t write; 215 216 read = pipe->read; 217 write = pipe->write; 218 219 if (read <= write) { 220 if (requested_sz > (write - read)) { 221 return -EINVAL; 222 } 223 224 read += requested_sz; 225 } else { 226 sz = spdk_min(requested_sz, pipe->sz - read); 227 228 read += sz; 229 if (read > pipe->sz - 1) { 230 read = 0; 231 } 232 requested_sz -= sz; 233 234 if (requested_sz > 0) { 235 if (requested_sz > write) { 236 return -EINVAL; 237 } 238 239 read = requested_sz; 240 } 241 } 242 243 pipe->read = read; 244 245 return 0; 246 } 247