/
lring.go
270 lines (208 loc) · 6.07 KB
/
lring.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019-2023 Intel Corporation
*/
package cne
/*
#include <stdint.h>
#include <cne_ring.h>
#define RING_DEFAULT_ELEM_SZ sizeof(void *)
*/
import "C"
import (
"fmt"
"unsafe"
)
var (
RingFlagSingleProducer = "SP_ENQ" // Single producer string
RingFlagSingleConsumer = "SC_DEQ" // Single consumer string
RingFlagExactSize = "EXACT_SIZE" // Exact size string
RingFlagSingleProducerValue uint = C.RING_F_SP_ENQ // Single producer value
RingFlagSingleConsumerValue uint = C.RING_F_SC_DEQ // Single consumer value
RingFlagExactSizeValue uint = C.RING_F_EXACT_SZ // Exact Size value
)
type ringFlagsMap map[string]uint
type stringFlagsMap map[uint]string
var ringFlags ringFlagsMap
var stringFlags stringFlagsMap
// LocklessRing structure contains internal information for a lockless ring.
type LocklessRing struct {
flags uint // Ring flags
name string // Name of the ring
elementSz uint // The size of the element in the ring.
elementCnt uint // The number of elements in the ring.
ring unsafe.Pointer // The private ring pointer
}
func init() {
// Create a map of flags and flag values.
ringFlags = make(map[string]uint)
ringFlags[RingFlagSingleProducer] = C.RING_F_SP_ENQ
ringFlags[RingFlagSingleConsumer] = C.RING_F_SC_DEQ
ringFlags[RingFlagExactSize] = C.RING_F_EXACT_SZ
stringFlags = make(map[uint]string)
stringFlags[C.RING_F_SP_ENQ] = RingFlagSingleProducer
stringFlags[C.RING_F_SC_DEQ] = RingFlagSingleConsumer
stringFlags[C.RING_F_EXACT_SZ] = RingFlagExactSize
}
// Convert the ring options from strings to a flag value
func convertRingOptions(strFlags []string) uint {
var flags uint = 0
if strFlags == nil {
return flags
}
for _, s := range strFlags {
f, ok := ringFlags[s]
if ok {
flags |= f
}
}
return flags
}
// Convert the ring option value to a set of option strings
func ringOptionsToStrings(flags uint) []string {
str := make([]string, 0)
for v, s := range stringFlags {
if (v & flags) != 0 {
str = append(str, s)
}
}
return str
}
// LRingCreateElem creates the lockless ring given the specified arguments and element size.
//
// The name is used to give the ring a name.
// The elementSz is the element size of each element in the ring.
// The count is used to set the max number of elements in the ring.
// strFlags are used in creating the lockless ring.
//
// Returns the internal lockless ring object or error value is set
func LRingCreateElem(name string, elementSz, count uint, strFlags []string) (*LocklessRing, error) {
if count == 0 {
return nil, fmt.Errorf("Count is zero")
}
if elementSz == 0 {
elementSz = C.RING_DEFAULT_ELEM_SZ
}
flags := convertRingOptions(strFlags)
lr := &LocklessRing{name: name, elementSz: elementSz, elementCnt: count, flags: flags}
n := C.CString(name)
defer C.free(unsafe.Pointer(n))
lr.ring = C.cne_ring_create(n, C.uint(elementSz), C.uint(count), C.uint(flags))
if lr.ring == nil {
return nil, fmt.Errorf("failed to create lockless ring")
}
return lr, nil
}
// NewLRing create a lockless ring using default element size of 8 bytes.
//
// The name is used to give the ring a name.
// The count is used to set the max number of elements in the ring.
// strFlags are used in creating the lockless ring.
//
// Returns the internal lockless ring object or error value is set
func NewLRing(name string, count uint, strFlags []string) (*LocklessRing, error) {
if count == 0 {
return nil, fmt.Errorf("Count is zero")
}
return LRingCreateElem(name, C.RING_DEFAULT_ELEM_SZ, count, strFlags)
}
// Destroy a lockless ring object given the valid LocklessRing structure pointer.
func (lr *LocklessRing) Destroy() {
if lr != nil {
C.cne_ring_free(lr.ring)
}
}
// EnqueueN enqueues N number of elements into a lockless ring.
func (lr *LocklessRing) EnqueueN(values []uintptr, cnt int) int {
if lr.ring != nil {
val := (*unsafe.Pointer)(unsafe.Pointer(&values[0]))
n := C.cne_ring_enqueue_burst(lr.ring, val, C.uint(cnt), nil)
return int(n)
}
return 0
}
// DequeueN dequeue a number of elements from the ring defined by the specified count
func (lr *LocklessRing) DequeueN(values []uintptr, cnt int) int {
if lr.ring != nil {
val := (*unsafe.Pointer)(unsafe.Pointer(&values[0]))
n := C.cne_ring_dequeue_burst(lr.ring, val, C.uint(cnt), nil)
return int(n)
}
return 0
}
// Dump the lockless ring information to the console.
func (lr *LocklessRing) Dump() {
if lr != nil {
C.cne_ring_dump(nil, lr.ring)
}
}
// Name returns the name of the lockless ring.
func (lr *LocklessRing) Name() string {
if lr == nil {
return ""
}
return lr.name
}
// Flags returns the flags of the lockless ring.
func (lr *LocklessRing) Flags() []string {
if lr == nil {
return nil
}
strFlags := ringOptionsToStrings(lr.flags)
return strFlags
}
// RawFlags returns the flags of the lockless ring.
func (lr *LocklessRing) RawFlags() uint {
if lr == nil {
return 0
}
return lr.flags
}
// Size returns the size of the lockless ring.
func (lr *LocklessRing) Size() uint {
if lr == nil {
return 0
}
return lr.elementCnt
}
// ElemSize returns the size of each element in the ring.
func (lr *LocklessRing) ElemSize() uint {
if lr == nil {
return 0
}
return lr.elementSz
}
// Count returns the number of elements currently in the ring
func (lr *LocklessRing) Count() uint {
if lr == nil {
return 0
}
return uint(C.cne_ring_count(lr.ring))
}
// FreeCount returns the number of elements currently free in the ring
func (lr *LocklessRing) FreeCount() uint {
if lr == nil {
return 0
}
return uint(C.cne_ring_free_count(lr.ring))
}
// Full returns true if the ring is full.
func (lr *LocklessRing) Full() bool {
if lr == nil {
return true
}
return C.cne_ring_full(lr.ring) > 0
}
// Empty returns true if the ring is empty.
func (lr *LocklessRing) Empty() bool {
if lr == nil {
return true
}
return C.cne_ring_empty(lr.ring) > 0
}
// Pointer returns the pointer to the C ring struct.
func (lr *LocklessRing) Pointer() unsafe.Pointer {
if lr == nil {
return nil
}
return lr.ring
}