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#ifndef BCM_QUEUE_H
31#define BCM_QUEUE_H
32#ifndef EMBEDDED
33#define EMBEDDED 1
34#endif
35
36
37
38
39
40
41typedef void *PQQ_ENTRY;
42
43
44typedef struct { int counter; } atomic_t;
45
46
47
48
49
50
51
52
53
54
55
56extern __inline void
57atomic_set(atomic_t* entry, int val)
58{
59 entry->counter = val;
60}
61extern __inline int
62atomic_read(atomic_t* entry)
63{
64 return entry->counter;
65}
66extern __inline void
67atomic_inc(atomic_t* entry)
68{
69 if(entry)
70 entry->counter++;
71}
72
73extern __inline void
74atomic_dec(atomic_t* entry)
75{
76 if(entry)
77 entry->counter--;
78}
79
80extern __inline void
81atomic_sub(int a, atomic_t* entry)
82{
83 if(entry)
84 entry->counter -= a;
85}
86extern __inline void
87atomic_add(int a, atomic_t* entry)
88{
89 if(entry)
90 entry->counter += a;
91}
92
93
94
95typedef struct {
96 unsigned int Head;
97 unsigned int Tail;
98 unsigned int Size;
99 atomic_t EntryCnt;
100 PQQ_ENTRY Array[1];
101} QQ_CONTAINER, *PQQ_CONTAINER;
102
103
104
105#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \
106 \
107 typedef struct { \
108 QQ_CONTAINER Container; \
109 PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \
110 } _QUEUE_TYPE, *P##_QUEUE_TYPE
111
112
113
114
115
116
117#if DBG
118#undef QQ_NO_OVERFLOW_CHECK
119#undef QQ_NO_UNDERFLOW_CHECK
120#endif
121
122#ifdef QQ_USE_MACROS
123
124#else
125
126#ifdef QQ_NO_INLINE
127#define __inline
128#endif
129
130
131
132
133
134
135extern __inline void
136QQ_InitQueue(
137PQQ_CONTAINER pQueue,
138unsigned int QueueSize) {
139 pQueue->Head = 0;
140 pQueue->Tail = 0;
141 pQueue->Size = QueueSize+1;
142 atomic_set(&pQueue->EntryCnt, 0);
143}
144
145
146
147
148
149
150
151extern __inline char
152QQ_Full(
153PQQ_CONTAINER pQueue) {
154 unsigned int NewHead;
155
156 NewHead = (pQueue->Head + 1) % pQueue->Size;
157
158 return(NewHead == pQueue->Tail);
159}
160
161
162
163
164
165
166
167extern __inline char
168QQ_Empty(
169PQQ_CONTAINER pQueue) {
170 return(pQueue->Head == pQueue->Tail);
171}
172
173
174
175
176
177
178
179extern __inline unsigned int
180QQ_GetSize(
181PQQ_CONTAINER pQueue) {
182 return pQueue->Size;
183}
184
185
186
187
188
189
190
191extern __inline unsigned int
192QQ_GetEntryCnt(
193PQQ_CONTAINER pQueue) {
194 return atomic_read(&pQueue->EntryCnt);
195}
196
197
198
199
200
201
202
203
204
205extern __inline char
206QQ_PushHead(
207PQQ_CONTAINER pQueue,
208PQQ_ENTRY pEntry) {
209 unsigned int Head;
210
211 Head = (pQueue->Head + 1) % pQueue->Size;
212
213#if !defined(QQ_NO_OVERFLOW_CHECK)
214 if(Head == pQueue->Tail) {
215 return 0;
216 }
217#endif
218
219 pQueue->Array[pQueue->Head] = pEntry;
220 wmb();
221 pQueue->Head = Head;
222 atomic_inc(&pQueue->EntryCnt);
223
224 return -1;
225}
226
227
228
229
230
231
232
233
234
235extern __inline char
236QQ_PushTail(
237PQQ_CONTAINER pQueue,
238PQQ_ENTRY pEntry) {
239 unsigned int Tail;
240
241 Tail = pQueue->Tail;
242 if(Tail == 0) {
243 Tail = pQueue->Size;
244 }
245 Tail--;
246
247#if !defined(QQ_NO_OVERFLOW_CHECK)
248 if(Tail == pQueue->Head) {
249 return 0;
250 }
251#endif
252
253 pQueue->Array[Tail] = pEntry;
254 wmb();
255 pQueue->Tail = Tail;
256 atomic_inc(&pQueue->EntryCnt);
257
258 return -1;
259}
260
261
262
263
264
265
266
267extern __inline PQQ_ENTRY
268QQ_PopHead(
269PQQ_CONTAINER pQueue) {
270 unsigned int Head;
271 PQQ_ENTRY Entry;
272
273 Head = pQueue->Head;
274
275#if !defined(QQ_NO_UNDERFLOW_CHECK)
276 if(Head == pQueue->Tail) {
277 return (PQQ_ENTRY) 0;
278 }
279#endif
280
281 if(Head == 0) {
282 Head = pQueue->Size;
283 }
284 Head--;
285
286 Entry = pQueue->Array[Head];
287#ifdef EMBEDDED
288 membar();
289#else
290 mb();
291#endif
292 pQueue->Head = Head;
293 atomic_dec(&pQueue->EntryCnt);
294
295 return Entry;
296}
297
298
299
300
301
302
303
304extern __inline PQQ_ENTRY
305QQ_PopTail(
306PQQ_CONTAINER pQueue) {
307 unsigned int Tail;
308 PQQ_ENTRY Entry;
309
310 Tail = pQueue->Tail;
311
312#if !defined(QQ_NO_UNDERFLOW_CHECK)
313 if(Tail == pQueue->Head) {
314 return (PQQ_ENTRY) 0;
315 }
316#endif
317
318 Entry = pQueue->Array[Tail];
319#ifdef EMBEDDED
320 membar();
321#else
322 mb();
323#endif
324 pQueue->Tail = (Tail + 1) % pQueue->Size;
325 atomic_dec(&pQueue->EntryCnt);
326
327 return Entry;
328}
329
330
331
332
333
334
335
336extern __inline PQQ_ENTRY
337QQ_GetHead(
338 PQQ_CONTAINER pQueue,
339 unsigned int Idx)
340{
341 if(Idx >= atomic_read(&pQueue->EntryCnt))
342 {
343 return (PQQ_ENTRY) 0;
344 }
345
346 if(pQueue->Head > Idx)
347 {
348 Idx = pQueue->Head - Idx;
349 }
350 else
351 {
352 Idx = pQueue->Size - (Idx - pQueue->Head);
353 }
354 Idx--;
355
356 return pQueue->Array[Idx];
357}
358
359
360
361
362
363
364
365extern __inline PQQ_ENTRY
366QQ_GetTail(
367 PQQ_CONTAINER pQueue,
368 unsigned int Idx)
369{
370 if(Idx >= atomic_read(&pQueue->EntryCnt))
371 {
372 return (PQQ_ENTRY) 0;
373 }
374
375 Idx += pQueue->Tail;
376 if(Idx >= pQueue->Size)
377 {
378 Idx = Idx - pQueue->Size;
379 }
380
381 return pQueue->Array[Idx];
382}
383
384#endif
385
386
387#endif
388