windows-nt/Source/XPSP1/NT/net/tcpip/driver/inc/queue.h
2020-09-26 16:20:57 +08:00

193 lines
4.2 KiB
C

/********************************************************************/
/** 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__