/
githubmirror
/
rdma-core
Обзор
Документация
Войти
/
githubmirror
/
rdma-core
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
providers/mana/shadow_queue.h
151 строка
4 KB
Konstantin Taranov
providers/mana: unify rc_qp to be rnic_qp
04 фев 2026, 13:11
04 фев 2026, 13:11
b7f6164
Код
Авторство
О чём код?
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* * Copyright (c) 2024, Microsoft Corporation. All rights reserved. */ #ifndef _SHADOW_QUEUE_H_ #define _SHADOW_QUEUE_H_ #include <stdio.h> #include <linux/types.h> #include <endian.h> #include <infiniband/verbs.h> #include <sys/mman.h> #include <util/util.h> #include <stdatomic.h> typedef _Atomic(uint64_t) _atomic_t; #define MANA_NO_SIGNAL_WC (0xff) struct shadow_wqe_header { /* ibv_wc_opcode */ uint64_t opcode : 8; /* ibv_wc_flags or MANA_NO_SIGNAL_WC */ uint64_t flags : 8; uint64_t posted_wqe_size_in_bu : 8; /* ibv_wc_status */ uint64_t vendor_error : 12; uint64_t unmasked_queue_offset : 28; uint64_t wr_id; }; struct rnic_sq_shadow_wqe { struct shadow_wqe_header header; uint32_t end_psn; uint32_t read_posted_wqe_size_in_bu; }; struct rnic_rq_shadow_wqe { struct shadow_wqe_header header; uint32_t byte_len; uint32_t imm_or_rkey; }; struct shadow_queue { uint64_t prod_idx; uint64_t cons_idx; uint64_t next_to_signal_idx; uint32_t length; uint32_t stride; void *buffer; }; static inline void reset_shadow_queue(struct shadow_queue *queue) { queue->prod_idx = 0; queue->cons_idx = 0; queue->next_to_signal_idx = 0; } int create_shadow_queue(struct shadow_queue *queue, uint32_t length, uint32_t stride); void destroy_shadow_queue(struct shadow_queue *queue); static inline _atomic_t *producer(struct shadow_queue *queue) { return (_atomic_t *)&queue->prod_idx; } static inline _atomic_t *consumer(struct shadow_queue *queue) { return (_atomic_t *)&queue->cons_idx; } static inline struct shadow_wqe_header * shadow_queue_get_element(struct shadow_queue *queue, uint64_t unmasked_index) { uint32_t index = unmasked_index & (queue->length - 1); return (struct shadow_wqe_header *)((uint8_t *)queue->buffer + index * queue->stride); } static inline bool shadow_queue_full(struct shadow_queue *queue) { uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_relaxed); uint64_t cons_idx = atomic_load_explicit(consumer(queue), memory_order_acquire); return (prod_idx - cons_idx) >= queue->length; } static inline bool shadow_queue_empty(struct shadow_queue *queue) { uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_acquire); uint64_t cons_idx = atomic_load_explicit(consumer(queue), memory_order_relaxed); return (prod_idx == cons_idx); } static inline struct shadow_wqe_header * shadow_queue_producer_entry(struct shadow_queue *queue) { uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_relaxed); return shadow_queue_get_element(queue, prod_idx); } static inline void shadow_queue_advance_producer(struct shadow_queue *queue) { uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_relaxed); atomic_store_explicit(producer(queue), prod_idx + 1, memory_order_release); } static inline void shadow_queue_advance_consumer(struct shadow_queue *queue) { uint64_t cons_idx = atomic_load_explicit(consumer(queue), memory_order_relaxed); atomic_store_explicit(consumer(queue), cons_idx + 1, memory_order_release); } static inline struct shadow_wqe_header * shadow_queue_get_next_to_consume(struct shadow_queue *queue) { uint64_t cons_idx = atomic_load_explicit(consumer(queue), memory_order_relaxed); uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_acquire); if (cons_idx == prod_idx) return NULL; return shadow_queue_get_element(queue, cons_idx); } static inline struct shadow_wqe_header * shadow_queue_get_next_to_signal(struct shadow_queue *queue) { uint64_t prod_idx = atomic_load_explicit(producer(queue), memory_order_acquire); uint64_t cons_idx = atomic_load_explicit(consumer(queue), memory_order_relaxed); struct shadow_wqe_header *wqe = NULL; queue->next_to_signal_idx = max(queue->next_to_signal_idx, cons_idx); while (queue->next_to_signal_idx < prod_idx) { wqe = shadow_queue_get_element(queue, queue->next_to_signal_idx); queue->next_to_signal_idx++; if (wqe->flags != MANA_NO_SIGNAL_WC) return wqe; } return NULL; } #endif //_SHADOW_QUEUE_H_