DPDK  25.03.0
rte_ring_generic_pvt.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2010-2017 Intel Corporation
4  * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
5  * All rights reserved.
6  * Derived from FreeBSD's bufring.h
7  * Used as BSD-3 Licensed with permission from Kip Macy.
8  */
9 
10 #ifndef _RTE_RING_GENERIC_PVT_H_
11 #define _RTE_RING_GENERIC_PVT_H_
12 
24 static __rte_always_inline void
25 __rte_ring_update_tail(struct rte_ring_headtail *ht, uint32_t old_val,
26  uint32_t new_val, uint32_t single, uint32_t enqueue)
27 {
28  if (enqueue)
29  rte_smp_wmb();
30  else
31  rte_smp_rmb();
32  /*
33  * If there are other enqueues/dequeues in progress that preceded us,
34  * we need to wait for them to complete
35  */
36  if (!single)
37  rte_wait_until_equal_32((volatile uint32_t *)(uintptr_t)&ht->tail, old_val,
38  rte_memory_order_relaxed);
39 
40  ht->tail = new_val;
41 }
42 
70 static __rte_always_inline unsigned int
71 __rte_ring_headtail_move_head(struct rte_ring_headtail *d,
72  const struct rte_ring_headtail *s, uint32_t capacity,
73  unsigned int is_st, unsigned int n,
74  enum rte_ring_queue_behavior behavior,
75  uint32_t *old_head, uint32_t *new_head, uint32_t *entries)
76 {
77  unsigned int max = n;
78  int success;
79 
80  do {
81  /* Reset n to the initial burst count */
82  n = max;
83 
84  *old_head = d->head;
85 
86  /* add rmb barrier to avoid load/load reorder in weak
87  * memory model. It is noop on x86
88  */
89  rte_smp_rmb();
90 
91  /*
92  * The subtraction is done between two unsigned 32bits value
93  * (the result is always modulo 32 bits even if we have
94  * *old_head > s->tail). So 'entries' is always between 0
95  * and capacity (which is < size).
96  */
97  *entries = (capacity + s->tail - *old_head);
98 
99  /* check that we have enough room in ring */
100  if (unlikely(n > *entries))
101  n = (behavior == RTE_RING_QUEUE_FIXED) ?
102  0 : *entries;
103 
104  if (n == 0)
105  return 0;
106 
107  *new_head = *old_head + n;
108  if (is_st) {
109  d->head = *new_head;
110  success = 1;
111  } else
112  success = rte_atomic32_cmpset(
113  (uint32_t *)(uintptr_t)&d->head,
114  *old_head, *new_head);
115  } while (unlikely(success == 0));
116  return n;
117 }
118 
119 #endif /* _RTE_RING_GENERIC_PVT_H_ */
static void rte_smp_rmb(void)
static int rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
#define __rte_always_inline
Definition: rte_common.h:456
rte_ring_queue_behavior
Definition: rte_ring_core.h:40
static __rte_always_inline void rte_wait_until_equal_32(volatile uint32_t *addr, uint32_t expected, rte_memory_order memorder)
Definition: rte_pause.h:95
#define unlikely(x)
static void rte_smp_wmb(void)
uint32_t capacity