2 /******************************************************************************/
4 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */
6 /* All rights reserved. */
8 /* This program is free software; you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation, located in the file LICENSE. */
12 /* Queue functions. */
13 /* void QQ_InitQueue(PQQ_CONTAINER pQueue) */
14 /* char QQ_Full(PQQ_CONTAINER pQueue) */
15 /* char QQ_Empty(PQQ_CONTAINER pQueue) */
16 /* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) */
17 /* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) */
18 /* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */
19 /* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */
20 /* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) */
21 /* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) */
22 /* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) */
23 /* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) */
27 /* 02/25/00 Hav Khauv Initial version. */
28 /******************************************************************************/
36 /******************************************************************************/
37 /* Queue definitions. */
38 /******************************************************************************/
40 /* Entry for queueing. */
41 typedef void *PQQ_ENTRY;
43 /* Linux Atomic Ops support */
44 typedef struct { int counter; } atomic_t;
48 * This combination of `inline' and `extern' has almost the effect of a
49 * macro. The way to use it is to put a function definition in a header
50 * file with these keywords, and put another copy of the definition
51 * (lacking `inline' and `extern') in a library file. The definition in
52 * the header file will cause most calls to the function to be inlined.
53 * If any uses of the function remain, they will refer to the single copy
57 atomic_set(atomic_t* entry, int val)
62 atomic_read(atomic_t* entry)
64 return entry->counter;
67 atomic_inc(atomic_t* entry)
74 atomic_dec(atomic_t* entry)
81 atomic_sub(int a, atomic_t* entry)
87 atomic_add(int a, atomic_t* entry)
94 /* Queue header -- base type. */
101 } QQ_CONTAINER, *PQQ_CONTAINER;
104 /* Declare queue type macro. */
105 #define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \
108 QQ_CONTAINER Container; \
109 PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \
110 } _QUEUE_TYPE, *P##_QUEUE_TYPE
114 /******************************************************************************/
115 /* Compilation switches. */
116 /******************************************************************************/
119 #undef QQ_NO_OVERFLOW_CHECK
120 #undef QQ_NO_UNDERFLOW_CHECK
129 #endif /* QQ_NO_INLINE */
131 /******************************************************************************/
135 /******************************************************************************/
138 PQQ_CONTAINER pQueue,
139 unsigned int QueueSize) {
142 pQueue->Size = QueueSize+1;
143 atomic_set(&pQueue->EntryCnt, 0);
148 /******************************************************************************/
152 /******************************************************************************/
155 PQQ_CONTAINER pQueue) {
156 unsigned int NewHead;
158 NewHead = (pQueue->Head + 1) % pQueue->Size;
160 return(NewHead == pQueue->Tail);
165 /******************************************************************************/
169 /******************************************************************************/
172 PQQ_CONTAINER pQueue) {
173 return(pQueue->Head == pQueue->Tail);
178 /******************************************************************************/
182 /******************************************************************************/
183 extern __inline unsigned int
185 PQQ_CONTAINER pQueue) {
191 /******************************************************************************/
195 /******************************************************************************/
196 extern __inline unsigned int
198 PQQ_CONTAINER pQueue) {
199 return atomic_read(&pQueue->EntryCnt);
200 } /* QQ_GetEntryCnt */
204 /******************************************************************************/
208 /* TRUE entry was added successfully. */
209 /* FALSE queue is full. */
210 /******************************************************************************/
213 PQQ_CONTAINER pQueue,
217 Head = (pQueue->Head + 1) % pQueue->Size;
219 #if !defined(QQ_NO_OVERFLOW_CHECK)
220 if(Head == pQueue->Tail) {
223 #endif /* QQ_NO_OVERFLOW_CHECK */
225 pQueue->Array[pQueue->Head] = pEntry;
228 atomic_inc(&pQueue->EntryCnt);
235 /******************************************************************************/
239 /* TRUE entry was added successfully. */
240 /* FALSE queue is full. */
241 /******************************************************************************/
244 PQQ_CONTAINER pQueue,
254 #if !defined(QQ_NO_OVERFLOW_CHECK)
255 if(Tail == pQueue->Head) {
258 #endif /* QQ_NO_OVERFLOW_CHECK */
260 pQueue->Array[Tail] = pEntry;
263 atomic_inc(&pQueue->EntryCnt);
270 /******************************************************************************/
274 /******************************************************************************/
275 extern __inline PQQ_ENTRY
277 PQQ_CONTAINER pQueue) {
283 #if !defined(QQ_NO_UNDERFLOW_CHECK)
284 if(Head == pQueue->Tail) {
285 return (PQQ_ENTRY) 0;
287 #endif /* QQ_NO_UNDERFLOW_CHECK */
294 Entry = pQueue->Array[Head];
301 atomic_dec(&pQueue->EntryCnt);
308 /******************************************************************************/
312 /******************************************************************************/
313 extern __inline PQQ_ENTRY
315 PQQ_CONTAINER pQueue) {
321 #if !defined(QQ_NO_UNDERFLOW_CHECK)
322 if(Tail == pQueue->Head) {
323 return (PQQ_ENTRY) 0;
325 #endif /* QQ_NO_UNDERFLOW_CHECK */
327 Entry = pQueue->Array[Tail];
333 pQueue->Tail = (Tail + 1) % pQueue->Size;
334 atomic_dec(&pQueue->EntryCnt);
341 /******************************************************************************/
345 /******************************************************************************/
346 extern __inline PQQ_ENTRY
348 PQQ_CONTAINER pQueue,
351 if(Idx >= atomic_read(&pQueue->EntryCnt))
353 return (PQQ_ENTRY) 0;
356 if(pQueue->Head > Idx)
358 Idx = pQueue->Head - Idx;
362 Idx = pQueue->Size - (Idx - pQueue->Head);
366 return pQueue->Array[Idx];
371 /******************************************************************************/
375 /******************************************************************************/
376 extern __inline PQQ_ENTRY
378 PQQ_CONTAINER pQueue,
381 if(Idx >= atomic_read(&pQueue->EntryCnt))
383 return (PQQ_ENTRY) 0;
387 if(Idx >= pQueue->Size)
389 Idx = Idx - pQueue->Size;
392 return pQueue->Array[Idx];
395 #endif /* QQ_USE_MACROS */