LCOV - code coverage report
Current view: top level - spdk/lib/util - pipe.c (source / functions) Hit Total Coverage
Test: Combined Lines: 156 165 94.5 %
Date: 2024-07-13 18:15:50 Functions: 12 12 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 82 104 78.8 %

           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                 :      12534 : spdk_pipe_create(void *buf, uint32_t sz)
      33                 :            : {
      34                 :            :         struct spdk_pipe *pipe;
      35                 :            : 
      36                 :      12534 :         pipe = calloc(1, sizeof(*pipe));
      37         [ -  + ]:      12534 :         if (pipe == NULL) {
      38                 :          0 :                 return NULL;
      39                 :            :         }
      40                 :            : 
      41                 :      12534 :         pipe->buf = buf;
      42                 :      12534 :         pipe->sz = sz;
      43                 :            : 
      44                 :      12534 :         return pipe;
      45                 :            : }
      46                 :            : 
      47                 :            : void *
      48                 :      13129 : spdk_pipe_destroy(struct spdk_pipe *pipe)
      49                 :            : {
      50                 :            :         void *buf;
      51                 :            : 
      52         [ +  + ]:      13129 :         if (pipe == NULL) {
      53                 :        595 :                 return NULL;
      54                 :            :         }
      55                 :            : 
      56         [ +  + ]:      12534 :         if (pipe->group) {
      57                 :         36 :                 spdk_pipe_group_remove(pipe->group, pipe);
      58                 :            :         }
      59                 :            : 
      60                 :      12534 :         buf = pipe->buf;
      61                 :      12534 :         free(pipe);
      62                 :      12534 :         return buf;
      63                 :            : }
      64                 :            : 
      65                 :            : static void
      66                 :   15257702 : pipe_alloc_buf_from_group(struct spdk_pipe *pipe)
      67                 :            : {
      68                 :            :         struct spdk_pipe_buf *buf;
      69                 :            :         struct spdk_pipe_group *group;
      70                 :            : 
      71         [ -  + ]:   15257702 :         assert(pipe->group != NULL);
      72                 :   15257702 :         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                 :   15257702 :         buf = SLIST_FIRST(&group->bufs);
      77         [ +  - ]:   15257702 :         while (buf != NULL) {
      78         [ +  - ]:   15257702 :                 if (buf->sz == pipe->sz) {
      79                 :            :                         /* TODO: Could track the previous and do an SLIST_REMOVE_AFTER */
      80   [ +  -  -  - ]:   15257702 :                         SLIST_REMOVE(&pipe->group->bufs, buf, spdk_pipe_buf, link);
      81                 :   15257702 :                         pipe->buf = (void *)buf;
      82                 :   15257702 :                         return;
      83                 :            :                 }
      84                 :          0 :                 buf = SLIST_NEXT(buf, link);
      85                 :            :         }
      86                 :            :         /* Should never get here. */
      87                 :          0 :         assert(false);
      88                 :            : }
      89                 :            : 
      90                 :            : int
      91                 :  229766297 : 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                 :  229766297 :         read = pipe->read;
      98                 :  229766297 :         write = pipe->write;
      99                 :            : 
     100   [ +  +  +  +  :  229766297 :         if (pipe->full || requested_sz == 0) {
                   +  + ]
     101                 :         12 :                 iovs[0].iov_base = NULL;
     102                 :         12 :                 iovs[0].iov_len = 0;
     103                 :         12 :                 return 0;
     104                 :            :         }
     105                 :            : 
     106         [ +  + ]:  229766285 :         if (pipe->buf == NULL) {
     107                 :   15256754 :                 pipe_alloc_buf_from_group(pipe);
     108                 :            :         }
     109                 :            : 
     110         [ +  + ]:  229766285 :         if (read <= write) {
     111                 :  229766273 :                 sz = spdk_min(requested_sz, pipe->sz - write);
     112                 :            : 
     113                 :  229766273 :                 iovs[0].iov_base = pipe->buf + write;
     114                 :  229766273 :                 iovs[0].iov_len = sz;
     115                 :            : 
     116                 :  229766273 :                 requested_sz -= sz;
     117                 :            : 
     118         [ +  + ]:  229766273 :                 if (requested_sz > 0) {
     119                 :         18 :                         sz = spdk_min(requested_sz, read);
     120                 :            : 
     121         [ +  + ]:         18 :                         iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
     122                 :         18 :                         iovs[1].iov_len = sz;
     123                 :            :                 } else {
     124                 :  229766255 :                         iovs[1].iov_base = NULL;
     125                 :  229766255 :                         iovs[1].iov_len = 0;
     126                 :            :                 }
     127                 :            :         } else {
     128                 :         12 :                 sz = spdk_min(requested_sz, read - write);
     129                 :            : 
     130                 :         12 :                 iovs[0].iov_base = pipe->buf + write;
     131                 :         12 :                 iovs[0].iov_len = sz;
     132                 :         12 :                 iovs[1].iov_base = NULL;
     133                 :         12 :                 iovs[1].iov_len = 0;
     134                 :            :         }
     135                 :            : 
     136                 :  229766285 :         return iovs[0].iov_len + iovs[1].iov_len;
     137                 :            : }
     138                 :            : 
     139                 :            : int
     140                 :   25462411 : 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                 :   25462411 :         read = pipe->read;
     147                 :   25462411 :         write = pipe->write;
     148                 :            : 
     149   [ +  +  -  +  :   25462411 :         if (requested_sz > pipe->sz || pipe->full) {
                   -  + ]
     150                 :          6 :                 return -EINVAL;
     151                 :            :         }
     152                 :            : 
     153         [ +  + ]:   25462405 :         if (read <= write) {
     154         [ +  + ]:   25462387 :                 if (requested_sz > (pipe->sz - write) + read) {
     155                 :          6 :                         return -EINVAL;
     156                 :            :                 }
     157                 :            : 
     158                 :   25462381 :                 sz = spdk_min(requested_sz, pipe->sz - write);
     159                 :            : 
     160                 :   25462381 :                 write += sz;
     161         [ +  + ]:   25462381 :                 if (write == pipe->sz) {
     162                 :    3000064 :                         write = 0;
     163                 :            :                 }
     164                 :   25462381 :                 requested_sz -= sz;
     165                 :            : 
     166         [ +  + ]:   25462381 :                 if (requested_sz > 0) {
     167                 :          6 :                         write = requested_sz;
     168                 :            :                 }
     169                 :            :         } else {
     170         [ +  + ]:         18 :                 if (requested_sz > (read - write)) {
     171                 :         12 :                         return -EINVAL;
     172                 :            :                 }
     173                 :            : 
     174                 :          6 :                 write += requested_sz;
     175                 :            :         }
     176                 :            : 
     177         [ +  + ]:   25462387 :         if (read == write) {
     178                 :    3000064 :                 pipe->full = true;
     179                 :            :         }
     180                 :   25462387 :         pipe->write = write;
     181                 :            : 
     182                 :   25462387 :         return 0;
     183                 :            : }
     184                 :            : 
     185                 :            : uint32_t
     186                 :  358504276 : spdk_pipe_reader_bytes_available(struct spdk_pipe *pipe)
     187                 :            : {
     188                 :            :         uint32_t read;
     189                 :            :         uint32_t write;
     190                 :            : 
     191                 :  358504276 :         read = pipe->read;
     192                 :  358504276 :         write = pipe->write;
     193                 :            : 
     194   [ +  +  -  +  :  358504276 :         if (read == write && !pipe->full) {
                   +  - ]
     195                 :  227472052 :                 return 0;
     196         [ +  + ]:  131032224 :         } else if (read < write) {
     197                 :   72621132 :                 return write - read;
     198                 :            :         } else {
     199                 :   58411092 :                 return (pipe->sz - read) + write;
     200                 :            :         }
     201                 :            : }
     202                 :            : 
     203                 :            : int
     204                 :  142042458 : 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                 :  142042458 :         read = pipe->read;
     211                 :  142042458 :         write = pipe->write;
     212                 :            : 
     213   [ +  +  -  +  :  142042458 :         if ((read == write && !pipe->full) || requested_sz == 0) {
             +  +  +  + ]
     214                 :   13242467 :                 iovs[0].iov_base = NULL;
     215                 :   13242467 :                 iovs[0].iov_len = 0;
     216                 :   13242467 :                 iovs[1].iov_base = NULL;
     217                 :   13242467 :                 iovs[1].iov_len = 0;
     218         [ +  + ]:  128799991 :         } else if (read < write) {
     219                 :   82292473 :                 sz = spdk_min(requested_sz, write - read);
     220                 :            : 
     221                 :   82292473 :                 iovs[0].iov_base = pipe->buf + read;
     222                 :   82292473 :                 iovs[0].iov_len = sz;
     223                 :   82292473 :                 iovs[1].iov_base = NULL;
     224                 :   82292473 :                 iovs[1].iov_len = 0;
     225                 :            :         } else {
     226                 :   46507518 :                 sz = spdk_min(requested_sz, pipe->sz - read);
     227                 :            : 
     228                 :   46507518 :                 iovs[0].iov_base = pipe->buf + read;
     229                 :   46507518 :                 iovs[0].iov_len = sz;
     230                 :            : 
     231                 :   46507518 :                 requested_sz -= sz;
     232                 :            : 
     233         [ +  + ]:   46507518 :                 if (requested_sz > 0) {
     234                 :   43507460 :                         sz = spdk_min(requested_sz, write);
     235         [ +  + ]:   43507460 :                         iovs[1].iov_base = (sz == 0) ? NULL : pipe->buf;
     236                 :   43507460 :                         iovs[1].iov_len = sz;
     237                 :            :                 } else {
     238                 :    3000058 :                         iovs[1].iov_base = NULL;
     239                 :    3000058 :                         iovs[1].iov_len = 0;
     240                 :            :                 }
     241                 :            :         }
     242                 :            : 
     243                 :  142042458 :         return iovs[0].iov_len + iovs[1].iov_len;
     244                 :            : }
     245                 :            : 
     246                 :            : int
     247                 :  128799985 : 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                 :  128799985 :         read = pipe->read;
     254                 :  128799985 :         write = pipe->write;
     255                 :            : 
     256         [ -  + ]:  128799985 :         if (requested_sz == 0) {
     257                 :          0 :                 return 0;
     258                 :            :         }
     259                 :            : 
     260         [ +  + ]:  128799985 :         if (read < write) {
     261         [ +  + ]:   82292485 :                 if (requested_sz > (write - read)) {
     262                 :         12 :                         return -EINVAL;
     263                 :            :                 }
     264                 :            : 
     265                 :   82292473 :                 read += requested_sz;
     266                 :            :         } else {
     267                 :   46507500 :                 sz = spdk_min(requested_sz, pipe->sz - read);
     268                 :            : 
     269                 :   46507500 :                 read += sz;
     270         [ +  + ]:   46507500 :                 if (read == pipe->sz) {
     271                 :    3000051 :                         read = 0;
     272                 :            :                 }
     273                 :   46507500 :                 requested_sz -= sz;
     274                 :            : 
     275         [ +  + ]:   46507500 :                 if (requested_sz > 0) {
     276         [ -  + ]:          6 :                         if (requested_sz > write) {
     277                 :          0 :                                 return -EINVAL;
     278                 :            :                         }
     279                 :            : 
     280                 :          6 :                         read = requested_sz;
     281                 :            :                 }
     282                 :            :         }
     283                 :            : 
     284                 :            :         /* We know we advanced at least one byte, so the pipe isn't full. */
     285                 :  128799973 :         pipe->full = false;
     286                 :            : 
     287         [ +  + ]:  128799973 :         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                 :   25462352 :                 read = 0;
     291                 :   25462352 :                 pipe->write = 0;
     292                 :            : 
     293                 :            :                 /* Additionally, release the buffer to the shared pool */
     294         [ +  + ]:   25462352 :                 if (pipe->group) {
     295                 :   15249409 :                         struct spdk_pipe_buf *buf = (struct spdk_pipe_buf *)pipe->buf;
     296                 :   15249409 :                         buf->sz = pipe->sz;
     297                 :   15249409 :                         SLIST_INSERT_HEAD(&pipe->group->bufs, buf, link);
     298                 :   15249409 :                         pipe->buf = NULL;
     299                 :            :                 }
     300                 :            :         }
     301                 :            : 
     302                 :  128799973 :         pipe->read = read;
     303                 :            : 
     304                 :  128799973 :         return 0;
     305                 :            : }
     306                 :            : 
     307                 :            : struct spdk_pipe_group *
     308                 :       4442 : spdk_pipe_group_create(void)
     309                 :            : {
     310                 :            :         struct spdk_pipe_group *group;
     311                 :            : 
     312                 :       4442 :         group = calloc(1, sizeof(*group));
     313         [ -  + ]:       4442 :         if (!group) {
     314                 :          0 :                 return NULL;
     315                 :            :         }
     316                 :            : 
     317                 :       4442 :         SLIST_INIT(&group->bufs);
     318                 :            : 
     319                 :       4442 :         return group;
     320                 :            : }
     321                 :            : 
     322                 :            : void
     323                 :       4442 : spdk_pipe_group_destroy(struct spdk_pipe_group *group)
     324                 :            : {
     325         [ -  + ]:       4442 :         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                 :       4442 :         free(group);
     331                 :       4442 : }
     332                 :            : 
     333                 :            : int
     334                 :       8293 : spdk_pipe_group_add(struct spdk_pipe_group *group, struct spdk_pipe *pipe)
     335                 :            : {
     336                 :            :         struct spdk_pipe_buf *buf;
     337                 :            : 
     338         [ -  + ]:       8293 :         assert(pipe->group == NULL);
     339                 :            : 
     340                 :       8293 :         pipe->group = group;
     341   [ +  -  -  +  :       8293 :         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                 :       8293 :         buf = (struct spdk_pipe_buf *)pipe->buf;
     350                 :       8293 :         buf->sz = pipe->sz;
     351                 :       8293 :         SLIST_INSERT_HEAD(&group->bufs, buf, link);
     352                 :       8293 :         pipe->buf = NULL;
     353                 :       8293 :         return 0;
     354                 :            : }
     355                 :            : 
     356                 :            : int
     357                 :       8293 : spdk_pipe_group_remove(struct spdk_pipe_group *group, struct spdk_pipe *pipe)
     358                 :            : {
     359         [ -  + ]:       8293 :         assert(pipe->group == group);
     360                 :            : 
     361         [ +  + ]:       8293 :         if (pipe->buf == NULL) {
     362                 :            :                 /* Associate a buffer with the pipe before returning. */
     363                 :        948 :                 pipe_alloc_buf_from_group(pipe);
     364         [ -  + ]:        948 :                 assert(pipe->buf != NULL);
     365                 :            :         }
     366                 :            : 
     367                 :       8293 :         pipe->group = NULL;
     368                 :       8293 :         return 0;
     369                 :            : }

Generated by: LCOV version 1.14