diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/seastar/dpdk/drivers/event/sw/iq_chunk.h | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/seastar/dpdk/drivers/event/sw/iq_chunk.h')
-rw-r--r-- | src/seastar/dpdk/drivers/event/sw/iq_chunk.h | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/seastar/dpdk/drivers/event/sw/iq_chunk.h b/src/seastar/dpdk/drivers/event/sw/iq_chunk.h new file mode 100644 index 000000000..31d013eab --- /dev/null +++ b/src/seastar/dpdk/drivers/event/sw/iq_chunk.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ + +#ifndef _IQ_CHUNK_H_ +#define _IQ_CHUNK_H_ + +#include <stdint.h> +#include <stdbool.h> +#include <rte_eventdev.h> + +#define IQ_ROB_NAMESIZE 12 + +struct sw_queue_chunk { + struct rte_event events[SW_EVS_PER_Q_CHUNK]; + struct sw_queue_chunk *next; +} __rte_cache_aligned; + +static __rte_always_inline bool +iq_empty(struct sw_iq *iq) +{ + return (iq->count == 0); +} + +static __rte_always_inline uint16_t +iq_count(const struct sw_iq *iq) +{ + return iq->count; +} + +static __rte_always_inline struct sw_queue_chunk * +iq_alloc_chunk(struct sw_evdev *sw) +{ + struct sw_queue_chunk *chunk = sw->chunk_list_head; + sw->chunk_list_head = chunk->next; + chunk->next = NULL; + return chunk; +} + +static __rte_always_inline void +iq_free_chunk(struct sw_evdev *sw, struct sw_queue_chunk *chunk) +{ + chunk->next = sw->chunk_list_head; + sw->chunk_list_head = chunk; +} + +static __rte_always_inline void +iq_free_chunk_list(struct sw_evdev *sw, struct sw_queue_chunk *head) +{ + while (head) { + struct sw_queue_chunk *next; + next = head->next; + iq_free_chunk(sw, head); + head = next; + } +} + +static __rte_always_inline void +iq_init(struct sw_evdev *sw, struct sw_iq *iq) +{ + iq->head = iq_alloc_chunk(sw); + iq->tail = iq->head; + iq->head_idx = 0; + iq->tail_idx = 0; + iq->count = 0; +} + +static __rte_always_inline void +iq_enqueue(struct sw_evdev *sw, struct sw_iq *iq, const struct rte_event *ev) +{ + iq->tail->events[iq->tail_idx++] = *ev; + iq->count++; + + if (unlikely(iq->tail_idx == SW_EVS_PER_Q_CHUNK)) { + /* The number of chunks is defined in relation to the total + * number of inflight events and number of IQS such that + * allocation will always succeed. + */ + struct sw_queue_chunk *chunk = iq_alloc_chunk(sw); + iq->tail->next = chunk; + iq->tail = chunk; + iq->tail_idx = 0; + } +} + +static __rte_always_inline void +iq_pop(struct sw_evdev *sw, struct sw_iq *iq) +{ + iq->head_idx++; + iq->count--; + + if (unlikely(iq->head_idx == SW_EVS_PER_Q_CHUNK)) { + struct sw_queue_chunk *next = iq->head->next; + iq_free_chunk(sw, iq->head); + iq->head = next; + iq->head_idx = 0; + } +} + +static __rte_always_inline const struct rte_event * +iq_peek(struct sw_iq *iq) +{ + return &iq->head->events[iq->head_idx]; +} + +/* Note: the caller must ensure that count <= iq_count() */ +static __rte_always_inline uint16_t +iq_dequeue_burst(struct sw_evdev *sw, + struct sw_iq *iq, + struct rte_event *ev, + uint16_t count) +{ + struct sw_queue_chunk *current; + uint16_t total, index; + + count = RTE_MIN(count, iq_count(iq)); + + current = iq->head; + index = iq->head_idx; + total = 0; + + /* Loop over the chunks */ + while (1) { + struct sw_queue_chunk *next; + for (; index < SW_EVS_PER_Q_CHUNK;) { + ev[total++] = current->events[index++]; + + if (unlikely(total == count)) + goto done; + } + + /* Move to the next chunk */ + next = current->next; + iq_free_chunk(sw, current); + current = next; + index = 0; + } + +done: + if (unlikely(index == SW_EVS_PER_Q_CHUNK)) { + struct sw_queue_chunk *next = current->next; + iq_free_chunk(sw, current); + iq->head = next; + iq->head_idx = 0; + } else { + iq->head = current; + iq->head_idx = index; + } + + iq->count -= total; + + return total; +} + +static __rte_always_inline void +iq_put_back(struct sw_evdev *sw, + struct sw_iq *iq, + struct rte_event *ev, + unsigned int count) +{ + /* Put back events that fit in the current head chunk. If necessary, + * put back events in a new head chunk. The caller must ensure that + * count <= SW_EVS_PER_Q_CHUNK, to ensure that at most one new head is + * needed. + */ + uint16_t avail_space = iq->head_idx; + + if (avail_space >= count) { + const uint16_t idx = avail_space - count; + uint16_t i; + + for (i = 0; i < count; i++) + iq->head->events[idx + i] = ev[i]; + + iq->head_idx = idx; + } else if (avail_space < count) { + const uint16_t remaining = count - avail_space; + struct sw_queue_chunk *new_head; + uint16_t i; + + for (i = 0; i < avail_space; i++) + iq->head->events[i] = ev[remaining + i]; + + new_head = iq_alloc_chunk(sw); + new_head->next = iq->head; + iq->head = new_head; + iq->head_idx = SW_EVS_PER_Q_CHUNK - remaining; + + for (i = 0; i < remaining; i++) + iq->head->events[iq->head_idx + i] = ev[i]; + } + + iq->count += count; +} + +#endif /* _IQ_CHUNK_H_ */ |