DPDK  26.07.0
rte_ring_gcc_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_GCC_PVT_H_
11 #define _RTE_RING_GCC_PVT_H_
12 
48 static __rte_always_inline unsigned int
49 __rte_ring_headtail_move_head_st(struct rte_ring_headtail *d,
50  const struct rte_ring_headtail *s, uint32_t capacity,
51  unsigned int n,
52  enum rte_ring_queue_behavior behavior,
53  uint32_t *old_head, uint32_t *new_head, uint32_t *entries)
54 {
55 
56  *old_head = d->head;
57 
58  /* add rmb barrier to avoid load/load reorder in weak
59  * memory model. It is noop on x86
60  */
61  rte_smp_rmb();
62 
63  /*
64  * The subtraction is done between two unsigned 32bits value
65  * (the result is always modulo 32 bits even if we have
66  * *old_head > s->tail). So 'entries' is always between 0
67  * and capacity (which is < size).
68  */
69  *entries = capacity + s->tail - *old_head;
70 
71  /* check that we have enough room in ring */
72  if (unlikely(n > *entries))
73  n = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : *entries;
74 
75  if (n == 0)
76  return 0;
77 
78  *new_head = *old_head + n;
79  d->head = *new_head;
80  return n;
81 }
82 
109 static __rte_always_inline unsigned int
110 __rte_ring_headtail_move_head_mt(struct rte_ring_headtail *d,
111  const struct rte_ring_headtail *s, uint32_t capacity,
112  unsigned int n, enum rte_ring_queue_behavior behavior,
113  uint32_t *old_head, uint32_t *new_head, uint32_t *entries)
114 {
115  unsigned int max = n;
116  bool success;
117 
118  do {
119  /* Reset n to the initial burst count */
120  n = max;
121 
122  *old_head = d->head;
123 
124  /* add fence to avoid load/load reorder in weak
125  * memory model. It is noop on x86
126  */
127  __atomic_thread_fence(__ATOMIC_ACQUIRE);
128 
129  /*
130  * The subtraction is done between two unsigned 32bits value
131  * (the result is always modulo 32 bits even if we have
132  * *old_head > s->tail). So 'entries' is always between 0
133  * and capacity (which is < size).
134  */
135  *entries = (capacity + s->tail - *old_head);
136 
137  /* check that we have enough room in ring */
138  if (unlikely(n > *entries))
139  n = (behavior == RTE_RING_QUEUE_FIXED) ?
140  0 : *entries;
141 
142  if (n == 0)
143  return 0;
144 
145  *new_head = *old_head + n;
146 
147  success = __sync_bool_compare_and_swap(
148  (uint32_t *)(uintptr_t)&d->head,
149  *old_head, *new_head);
150  } while (unlikely(!success));
151 
152  return n;
153 }
154 
155 #endif /* _RTE_RING_GCC_PVT_H_ */
static void rte_smp_rmb(void)
#define __rte_always_inline
Definition: rte_common.h:506
rte_ring_queue_behavior
Definition: rte_ring_core.h:40
#define unlikely(x)
uint32_t capacity