|
|
/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1990-2000 **/ /********************************************************************/ /* :ts=4 */ #ifndef __QUEUE_H__
#define __QUEUE_H__
//** QUEUE.H - TCP/UDP queuing definitons.
//
// This file contains the definitions for the queue functions used
// by the TCP/UDP code.
//
//* Definition of a queue linkage field.
struct Queue { struct Queue *q_next; struct Queue *q_prev; }; /* Queue */
typedef struct Queue Queue;
//* Initialize queue macro.
#define INITQ(q) { (q)->q_next = (q);\
(q)->q_prev = (q); }
//* Macro to check for queue empty.
#define EMPTYQ(q) ((q)->q_next == (q))
//* Place an element onto the end of the queue.
#define ENQUEUE(q, e) { (q)->q_prev->q_next = (e);\
(e)->q_prev = (q)->q_prev;\ (q)->q_prev = (e);\ (e)->q_next = (q); }
//* Remove an element from the head of the queue. This macro assumes the queue
// is not empty. The element is returned as type t, queued through linkage
// l.
#define DEQUEUE(q, ptr, t, l) {\
Queue *__tmp__;\ \ __tmp__ = (q)->q_next;\ (q)->q_next = __tmp__->q_next;\ __tmp__->q_next->q_prev = (q);\ (ptr) = STRUCT_OF(t, __tmp__, l);\ }
//* Peek at an element at the head of the queue. We return a pointer to it
// without removing anything.
#define PEEKQ(q, ptr, t, l) {\
Queue *__tmp__;\ \ __tmp__ = (q)->q_next;\ (ptr) = STRUCT_OF(t, __tmp__, l);\ }
//* Macro to push an element onto the head of a queue.
#define PUSHQ(q, e) { (e)->q_next = (q)->q_next;\
(q)->q_next->q_prev = (e);\ (e)->q_prev = (q);\ (q)->q_next = e; }
//* Macro to remove an element from the middle of a queue.
#define REMOVEQ(q) { (q)->q_next->q_prev = (q)->q_prev;\
(q)->q_prev->q_next = (q)->q_next; }
//** The following macros define methods for working with queue without
// dequeueing, mostly dealing with Queue structures directly.
//* Macro to define the end of a Q, used in walking a queue sequentially.
#define QEND(q) (q)
//* Macro to get the first on a queue.
#define QHEAD(q) (q)->q_next
//* Macro to get a structure, given a queue.
#define QSTRUCT(t, q, l) STRUCT_OF(t, (q), l)
//* Macro to get the next thing on q queue.
#define QNEXT(q) (q)->q_next
//* Macro to get the previous thing on q queue.
#define QPREV(q) (q)->q_prev
__inline VOID InterlockedEnqueue( IN Queue* Q, IN Queue* Item, IN CTELock* Lock) { CTELockHandle Handle; CTEGetLock(Lock, &Handle); ENQUEUE(Q, Item); CTEFreeLock(Lock, Handle); }
__inline VOID InterlockedEnqueueAtDpcLevel( IN Queue* Q, IN Queue* Item, IN CTELock* Lock) { CTELockHandle Handle; CTEGetLockAtDPC(Lock, &Handle); ENQUEUE(Q, Item); CTEFreeLockFromDPC(Lock, Handle); }
__inline Queue* InterlockedDequeueIfNotEmpty( IN Queue* Q, IN CTELock* Lock) { CTELockHandle Handle; Queue* Item = NULL; if (!EMPTYQ(Q)) { CTEGetLock(Lock, &Handle); if (!EMPTYQ(Q)) { Item = Q->q_next; Q->q_next = Item->q_next; Item->q_next->q_prev = Q; } CTEFreeLock(Lock, Handle); } return Item; }
__inline Queue* InterlockedDequeueIfNotEmptyAtIrql( IN Queue* Q, IN CTELock* Lock, IN KIRQL OrigIrql) { CTELockHandle Handle; Queue* Item = NULL; if (!EMPTYQ(Q)) { CTEGetLockAtIrql(Lock, OrigIrql, &Handle); if (!EMPTYQ(Q)) { Item = Q->q_next; Q->q_next = Item->q_next; Item->q_next->q_prev = Q; } CTEFreeLockAtIrql(Lock, OrigIrql, Handle); } return Item; }
__inline VOID InterlockedRemoveQueueItem( IN Queue* Q, IN CTELock* Lock) { CTELockHandle Handle; CTEGetLock(Lock, &Handle); REMOVEQ(Q); CTEFreeLock(Lock, Handle); }
__inline VOID InterlockedRemoveQueueItemAtDpcLevel( IN Queue* Q, IN CTELock* Lock) { CTELockHandle Handle; CTEGetLockAtDPC(Lock, &Handle); REMOVEQ(Q); CTEFreeLockFromDPC(Lock, Handle); }
#endif // __QUEUE_H__
|