Line data Source code
1 : /*
2 : * Copyright (c) 2018 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #ifndef included_ring_h
17 : #define included_ring_h
18 :
19 : #include <vppinfra/error.h>
20 : #include <vppinfra/format.h>
21 : #include <vppinfra/vec.h>
22 : #include <vppinfra/vector.h>
23 :
24 : typedef struct
25 : {
26 : u32 next, n_enq;
27 : } clib_ring_header_t;
28 :
29 : always_inline clib_ring_header_t *
30 0 : clib_ring_header (void *v)
31 : {
32 0 : return vec_header (v);
33 : }
34 :
35 : always_inline void
36 0 : clib_ring_new_inline (void **p, u32 elt_bytes, u32 size, u32 align)
37 : {
38 : void *v;
39 : clib_ring_header_t *h;
40 0 : vec_attr_t va = { .elt_sz = elt_bytes,
41 : .hdr_sz = sizeof (clib_ring_header_t),
42 : .align = align };
43 :
44 0 : v = _vec_alloc_internal (size, &va);
45 :
46 0 : h = clib_ring_header (v);
47 0 : h->next = 0;
48 0 : h->n_enq = 0;
49 0 : p[0] = v;
50 0 : }
51 :
52 : #define clib_ring_new_aligned(ring, size, align) \
53 : { clib_ring_new_inline ((void **)&(ring), sizeof(ring[0]), size, align); }
54 :
55 : #define clib_ring_new(ring, size) \
56 : { clib_ring_new_inline ((void **)&(ring), sizeof(ring[0]), size, 0);}
57 :
58 : #define clib_ring_free(f) vec_free ((f))
59 :
60 : always_inline u32
61 : clib_ring_n_enq (void *v)
62 : {
63 : clib_ring_header_t *h = clib_ring_header (v);
64 : return h->n_enq;
65 : }
66 :
67 : always_inline void *
68 0 : clib_ring_get_last_inline (void *v, u32 elt_bytes, int enqueue)
69 : {
70 0 : clib_ring_header_t *h = clib_ring_header (v);
71 : u32 slot;
72 :
73 0 : if (enqueue)
74 : {
75 0 : if (h->n_enq == _vec_len (v))
76 0 : return 0;
77 0 : slot = h->next;
78 0 : h->n_enq++;
79 0 : h->next++;
80 0 : if (h->next == _vec_len (v))
81 0 : h->next = 0;
82 : }
83 : else
84 : {
85 0 : if (h->n_enq == 0)
86 0 : return 0;
87 0 : slot = h->next == 0 ? _vec_len (v) - 1 : h->next - 1;
88 : }
89 :
90 0 : return (void *) ((u8 *) v + elt_bytes * slot);
91 : }
92 :
93 : #define clib_ring_enq(ring) \
94 : clib_ring_get_last_inline (ring, sizeof(ring[0]), 1)
95 :
96 : #define clib_ring_get_last(ring) \
97 : clib_ring_get_last_inline (ring, sizeof(ring[0]), 0)
98 :
99 : always_inline void *
100 0 : clib_ring_get_first_inline (void *v, u32 elt_bytes, int dequeue)
101 : {
102 0 : clib_ring_header_t *h = clib_ring_header (v);
103 : u32 slot;
104 :
105 0 : if (h->n_enq == 0)
106 0 : return 0;
107 :
108 0 : if (h->n_enq > h->next)
109 0 : slot = _vec_len (v) + h->next - h->n_enq;
110 : else
111 0 : slot = h->next - h->n_enq;
112 :
113 0 : if (dequeue)
114 0 : h->n_enq--;
115 :
116 0 : return (void *) ((u8 *) v + elt_bytes * slot);
117 : }
118 :
119 : #define clib_ring_deq(ring) \
120 : clib_ring_get_first_inline (ring, sizeof(ring[0]), 1)
121 :
122 : #define clib_ring_get_first(ring) \
123 : clib_ring_get_first_inline (ring, sizeof(ring[0]), 0)
124 :
125 : #endif /* included_ring_h */
126 :
127 : /*
128 : * fd.io coding-style-patch-verification: ON
129 : *
130 : * Local Variables:
131 : * eval: (c-set-style "gnu")
132 : * End:
133 : */
|