LCOV - code coverage report
Current view: top level - drivers/event/sw - iq_chunk.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 44 57 77.2 %
Date: 2024-12-01 18:57:19 Functions: 0 0 -
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 29 40 72.5 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2017 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef _IQ_CHUNK_H_
       6                 :            : #define _IQ_CHUNK_H_
       7                 :            : 
       8                 :            : #include <stdint.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <rte_eventdev.h>
      11                 :            : 
      12                 :            : struct __rte_cache_aligned sw_queue_chunk {
      13                 :            :         struct rte_event events[SW_EVS_PER_Q_CHUNK];
      14                 :            :         struct sw_queue_chunk *next;
      15                 :            : };
      16                 :            : 
      17                 :            : static __rte_always_inline bool
      18                 :            : iq_empty(struct sw_iq *iq)
      19                 :            : {
      20                 :            :         return (iq->count == 0);
      21                 :            : }
      22                 :            : 
      23                 :            : static __rte_always_inline uint16_t
      24                 :            : iq_count(const struct sw_iq *iq)
      25                 :            : {
      26   [ +  +  -  -  :       9903 :         return iq->count;
                   +  + ]
      27                 :            : }
      28                 :            : 
      29                 :            : static __rte_always_inline struct sw_queue_chunk *
      30                 :            : iq_alloc_chunk(struct sw_evdev *sw)
      31                 :            : {
      32                 :        323 :         struct sw_queue_chunk *chunk = sw->chunk_list_head;
      33                 :        323 :         sw->chunk_list_head = chunk->next;
      34                 :        323 :         chunk->next = NULL;
      35                 :            :         return chunk;
      36                 :            : }
      37                 :            : 
      38                 :            : static __rte_always_inline void
      39                 :            : iq_free_chunk(struct sw_evdev *sw, struct sw_queue_chunk *chunk)
      40                 :            : {
      41                 :       1477 :         chunk->next = sw->chunk_list_head;
      42                 :       1189 :         sw->chunk_list_head = chunk;
      43                 :            : }
      44                 :            : 
      45                 :            : static __rte_always_inline void
      46                 :            : iq_free_chunk_list(struct sw_evdev *sw, struct sw_queue_chunk *head)
      47                 :            : {
      48         [ +  + ]:        576 :         while (head) {
      49                 :            :                 struct sw_queue_chunk *next;
      50                 :        288 :                 next = head->next;
      51                 :            :                 iq_free_chunk(sw, head);
      52                 :            :                 head = next;
      53                 :            :         }
      54                 :            : }
      55                 :            : 
      56                 :            : static __rte_always_inline void
      57                 :            : iq_init(struct sw_evdev *sw, struct sw_iq *iq)
      58                 :            : {
      59                 :        288 :         iq->head = iq_alloc_chunk(sw);
      60                 :        288 :         iq->tail = iq->head;
      61                 :        288 :         iq->head_idx = 0;
      62                 :        288 :         iq->tail_idx = 0;
      63                 :        288 :         iq->count = 0;
      64                 :            : }
      65                 :            : 
      66                 :            : static __rte_always_inline void
      67                 :            : iq_enqueue(struct sw_evdev *sw, struct sw_iq *iq, const struct rte_event *ev)
      68                 :            : {
      69                 :       9455 :         iq->tail->events[iq->tail_idx++] = *ev;
      70                 :       9455 :         iq->count++;
      71                 :            : 
      72   [ +  +  +  +  :       9455 :         if (unlikely(iq->tail_idx == SW_EVS_PER_Q_CHUNK)) {
             +  +  -  + ]
      73                 :            :                 /* The number of chunks is defined in relation to the total
      74                 :            :                  * number of inflight events and number of IQS such that
      75                 :            :                  * allocation will always succeed.
      76                 :            :                  */
      77                 :            :                 struct sw_queue_chunk *chunk = iq_alloc_chunk(sw);
      78                 :         35 :                 iq->tail->next = chunk;
      79                 :         35 :                 iq->tail = chunk;
      80                 :         35 :                 iq->tail_idx = 0;
      81                 :            :         }
      82                 :            : }
      83                 :            : 
      84                 :            : static __rte_always_inline void
      85                 :            : iq_pop(struct sw_evdev *sw, struct sw_iq *iq)
      86                 :            : {
      87                 :         11 :         iq->head_idx++;
      88                 :         11 :         iq->count--;
      89                 :            : 
      90         [ -  + ]:         11 :         if (unlikely(iq->head_idx == SW_EVS_PER_Q_CHUNK)) {
      91                 :          0 :                 struct sw_queue_chunk *next = iq->head->next;
      92                 :            :                 iq_free_chunk(sw, iq->head);
      93                 :          0 :                 iq->head = next;
      94                 :          0 :                 iq->head_idx = 0;
      95                 :            :         }
      96                 :            : }
      97                 :            : 
      98                 :            : static __rte_always_inline const struct rte_event *
      99                 :            : iq_peek(struct sw_iq *iq)
     100                 :            : {
     101                 :         11 :         return &iq->head->events[iq->head_idx];
     102                 :            : }
     103                 :            : 
     104                 :            : /* Note: the caller must ensure that count <= iq_count() */
     105                 :            : static __rte_always_inline uint16_t
     106                 :            : iq_dequeue_burst(struct sw_evdev *sw,
     107                 :            :                  struct sw_iq *iq,
     108                 :            :                  struct rte_event *ev,
     109                 :            :                  uint16_t count)
     110                 :            : {
     111                 :            :         struct sw_queue_chunk *current;
     112                 :            :         uint16_t total, index;
     113                 :            : 
     114                 :       9288 :         count = RTE_MIN(count, iq_count(iq));
     115                 :            : 
     116                 :       9386 :         current = iq->head;
     117                 :       9386 :         index = iq->head_idx;
     118                 :            :         total = 0;
     119                 :            : 
     120                 :            :         /* Loop over the chunks */
     121                 :          0 :         while (1) {
     122                 :            :                 struct sw_queue_chunk *next;
     123   [ +  -  +  - ]:       9609 :                 for (; index < SW_EVS_PER_Q_CHUNK;) {
     124                 :       9609 :                         ev[total++] = current->events[index++];
     125                 :            : 
     126   [ +  +  +  + ]:       9609 :                         if (unlikely(total == count))
     127                 :       9386 :                                 goto done;
     128                 :            :                 }
     129                 :            : 
     130                 :            :                 /* Move to the next chunk */
     131                 :          0 :                 next = current->next;
     132                 :            :                 iq_free_chunk(sw, current);
     133                 :            :                 current = next;
     134                 :            :                 index = 0;
     135                 :            :         }
     136                 :            : 
     137                 :            : done:
     138   [ +  +  +  + ]:       9386 :         if (unlikely(index == SW_EVS_PER_Q_CHUNK)) {
     139                 :         35 :                 struct sw_queue_chunk *next = current->next;
     140                 :            :                 iq_free_chunk(sw, current);
     141                 :         35 :                 iq->head = next;
     142                 :         35 :                 iq->head_idx = 0;
     143                 :            :         } else {
     144                 :       9351 :                 iq->head = current;
     145                 :       9351 :                 iq->head_idx = index;
     146                 :            :         }
     147                 :            : 
     148         [ +  + ]:       9386 :         iq->count -= total;
     149                 :            : 
     150                 :            :         return total;
     151                 :            : }
     152                 :            : 
     153                 :            : static __rte_always_inline void
     154                 :            : iq_put_back(struct sw_evdev *sw,
     155                 :            :             struct sw_iq *iq,
     156                 :            :             struct rte_event *ev,
     157                 :            :             unsigned int count)
     158                 :            : {
     159                 :            :         /* Put back events that fit in the current head chunk. If necessary,
     160                 :            :          * put back events in a new head chunk. The caller must ensure that
     161                 :            :          * count <= SW_EVS_PER_Q_CHUNK, to ensure that at most one new head is
     162                 :            :          * needed.
     163                 :            :          */
     164                 :       4187 :         uint16_t avail_space = iq->head_idx;
     165                 :            : 
     166         [ +  - ]:       4187 :         if (avail_space >= count) {
     167                 :       4187 :                 const uint16_t idx = avail_space - count;
     168                 :            :                 uint16_t i;
     169                 :            : 
     170         [ +  + ]:       4352 :                 for (i = 0; i < count; i++)
     171                 :        165 :                         iq->head->events[idx + i] = ev[i];
     172                 :            : 
     173                 :       4187 :                 iq->head_idx = idx;
     174                 :            :         } else if (avail_space < count) {
     175                 :          0 :                 const uint16_t remaining = count - avail_space;
     176                 :            :                 struct sw_queue_chunk *new_head;
     177                 :            :                 uint16_t i;
     178                 :            : 
     179         [ #  # ]:          0 :                 for (i = 0; i < avail_space; i++)
     180                 :          0 :                         iq->head->events[i] = ev[remaining + i];
     181                 :            : 
     182                 :            :                 new_head = iq_alloc_chunk(sw);
     183                 :          0 :                 new_head->next = iq->head;
     184                 :          0 :                 iq->head = new_head;
     185                 :          0 :                 iq->head_idx = SW_EVS_PER_Q_CHUNK - remaining;
     186                 :            : 
     187         [ #  # ]:          0 :                 for (i = 0; i < remaining; i++)
     188                 :          0 :                         iq->head->events[iq->head_idx + i] = ev[i];
     189                 :            :         }
     190                 :            : 
     191                 :       4187 :         iq->count += count;
     192                 :            : }
     193                 :            : 
     194                 :            : #endif /* _IQ_CHUNK_H_ */

Generated by: LCOV version 1.14