Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
4.2 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-2000 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. #ifndef __QUEUE_H__
  7. #define __QUEUE_H__
  8. //** QUEUE.H - TCP/UDP queuing definitons.
  9. //
  10. // This file contains the definitions for the queue functions used
  11. // by the TCP/UDP code.
  12. //
  13. //* Definition of a queue linkage field.
  14. struct Queue {
  15. struct Queue *q_next;
  16. struct Queue *q_prev;
  17. }; /* Queue */
  18. typedef struct Queue Queue;
  19. //* Initialize queue macro.
  20. #define INITQ(q) { (q)->q_next = (q);\
  21. (q)->q_prev = (q); }
  22. //* Macro to check for queue empty.
  23. #define EMPTYQ(q) ((q)->q_next == (q))
  24. //* Place an element onto the end of the queue.
  25. #define ENQUEUE(q, e) { (q)->q_prev->q_next = (e);\
  26. (e)->q_prev = (q)->q_prev;\
  27. (q)->q_prev = (e);\
  28. (e)->q_next = (q); }
  29. //* Remove an element from the head of the queue. This macro assumes the queue
  30. // is not empty. The element is returned as type t, queued through linkage
  31. // l.
  32. #define DEQUEUE(q, ptr, t, l) {\
  33. Queue *__tmp__;\
  34. \
  35. __tmp__ = (q)->q_next;\
  36. (q)->q_next = __tmp__->q_next;\
  37. __tmp__->q_next->q_prev = (q);\
  38. (ptr) = STRUCT_OF(t, __tmp__, l);\
  39. }
  40. //* Peek at an element at the head of the queue. We return a pointer to it
  41. // without removing anything.
  42. #define PEEKQ(q, ptr, t, l) {\
  43. Queue *__tmp__;\
  44. \
  45. __tmp__ = (q)->q_next;\
  46. (ptr) = STRUCT_OF(t, __tmp__, l);\
  47. }
  48. //* Macro to push an element onto the head of a queue.
  49. #define PUSHQ(q, e) { (e)->q_next = (q)->q_next;\
  50. (q)->q_next->q_prev = (e);\
  51. (e)->q_prev = (q);\
  52. (q)->q_next = e; }
  53. //* Macro to remove an element from the middle of a queue.
  54. #define REMOVEQ(q) { (q)->q_next->q_prev = (q)->q_prev;\
  55. (q)->q_prev->q_next = (q)->q_next; }
  56. //** The following macros define methods for working with queue without
  57. // dequeueing, mostly dealing with Queue structures directly.
  58. //* Macro to define the end of a Q, used in walking a queue sequentially.
  59. #define QEND(q) (q)
  60. //* Macro to get the first on a queue.
  61. #define QHEAD(q) (q)->q_next
  62. //* Macro to get a structure, given a queue.
  63. #define QSTRUCT(t, q, l) STRUCT_OF(t, (q), l)
  64. //* Macro to get the next thing on q queue.
  65. #define QNEXT(q) (q)->q_next
  66. //* Macro to get the previous thing on q queue.
  67. #define QPREV(q) (q)->q_prev
  68. __inline
  69. VOID
  70. InterlockedEnqueue(
  71. IN Queue* Q,
  72. IN Queue* Item,
  73. IN CTELock* Lock)
  74. {
  75. CTELockHandle Handle;
  76. CTEGetLock(Lock, &Handle);
  77. ENQUEUE(Q, Item);
  78. CTEFreeLock(Lock, Handle);
  79. }
  80. __inline
  81. VOID
  82. InterlockedEnqueueAtDpcLevel(
  83. IN Queue* Q,
  84. IN Queue* Item,
  85. IN CTELock* Lock)
  86. {
  87. CTELockHandle Handle;
  88. CTEGetLockAtDPC(Lock, &Handle);
  89. ENQUEUE(Q, Item);
  90. CTEFreeLockFromDPC(Lock, Handle);
  91. }
  92. __inline
  93. Queue*
  94. InterlockedDequeueIfNotEmpty(
  95. IN Queue* Q,
  96. IN CTELock* Lock)
  97. {
  98. CTELockHandle Handle;
  99. Queue* Item = NULL;
  100. if (!EMPTYQ(Q)) {
  101. CTEGetLock(Lock, &Handle);
  102. if (!EMPTYQ(Q)) {
  103. Item = Q->q_next;
  104. Q->q_next = Item->q_next;
  105. Item->q_next->q_prev = Q;
  106. }
  107. CTEFreeLock(Lock, Handle);
  108. }
  109. return Item;
  110. }
  111. __inline
  112. Queue*
  113. InterlockedDequeueIfNotEmptyAtIrql(
  114. IN Queue* Q,
  115. IN CTELock* Lock,
  116. IN KIRQL OrigIrql)
  117. {
  118. CTELockHandle Handle;
  119. Queue* Item = NULL;
  120. if (!EMPTYQ(Q)) {
  121. CTEGetLockAtIrql(Lock, OrigIrql, &Handle);
  122. if (!EMPTYQ(Q)) {
  123. Item = Q->q_next;
  124. Q->q_next = Item->q_next;
  125. Item->q_next->q_prev = Q;
  126. }
  127. CTEFreeLockAtIrql(Lock, OrigIrql, Handle);
  128. }
  129. return Item;
  130. }
  131. __inline
  132. VOID
  133. InterlockedRemoveQueueItem(
  134. IN Queue* Q,
  135. IN CTELock* Lock)
  136. {
  137. CTELockHandle Handle;
  138. CTEGetLock(Lock, &Handle);
  139. REMOVEQ(Q);
  140. CTEFreeLock(Lock, Handle);
  141. }
  142. __inline
  143. VOID
  144. InterlockedRemoveQueueItemAtDpcLevel(
  145. IN Queue* Q,
  146. IN CTELock* Lock)
  147. {
  148. CTELockHandle Handle;
  149. CTEGetLockAtDPC(Lock, &Handle);
  150. REMOVEQ(Q);
  151. CTEFreeLockFromDPC(Lock, Handle);
  152. }
  153. #endif // __QUEUE_H__