Leaked source code of windows server 2003
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.

169 lines
5.1 KiB

  1. /*--------------------------------------------------------------------------
  2. | queue.c - queue code. This queue code serves the following need:
  3. It provides circular queue code which is fast and it does so without
  4. requiring a lock or semaphore between the get and put side of the queue.
  5. Simpler queue code exists which keeps a qcount member, but this requires
  6. a lock or semaphore in the implementation. By calculating everything
  7. based on the indexes we can run without a lock. This index arithmetic
  8. is a bit hairy(and may contain some additional overhead), but when
  9. working with a complex multiprocessor OS's, the ellimination of the lock
  10. is very handy.
  11. Copyright 1996-97 Comtrol Corporation. All rights reserved.
  12. |--------------------------------------------------------------------------*/
  13. #include "precomp.h"
  14. // much of the queue implementation are macros in the header file.
  15. /*--------------------------------------------------------------------------
  16. | q_flush_count_put - flush the queue and return number of bytes flushed
  17. from it. Assume Put side of queue will not be in a state of flux.
  18. |--------------------------------------------------------------------------*/
  19. int q_flush_count_put(Queue *queue)
  20. {
  21. int Count, QGet;
  22. // use a copy of QGet, since it may be changing at ISR level while we work.
  23. QGet = queue->QGet;
  24. // figure the number of bytes in the queue
  25. if ((Count = queue->QPut - QGet) < 0)
  26. Count += queue->QSize; // adjust for wrap
  27. // flush by setting QGet=QPut;
  28. queue->QPut = QGet;
  29. return Count; // return count of flushed chars
  30. }
  31. /*--------------------------------------------------------------------------
  32. | q_flush_count_get - flush the queue and return number of bytes flushed
  33. from it. Assume Get side of queue will not be in a state of flux.
  34. |--------------------------------------------------------------------------*/
  35. int q_flush_count_get(Queue *queue)
  36. {
  37. int Count, QPut;
  38. // use a copy of QPut, since it may be changing at ISR level while we work.
  39. QPut = queue->QPut;
  40. // figure the number of bytes in the queue
  41. if ((Count = QPut - queue->QGet) < 0)
  42. Count += queue->QSize; // adjust for wrap
  43. // flush by setting QGet=QPut;
  44. queue->QGet = QPut;
  45. return Count; // return count of flushed chars
  46. }
  47. /*----------------------------------
  48. q_room - return number of chars room in queue we can put.
  49. |----------------------------------*/
  50. int q_room(Queue *queue)
  51. {
  52. int QCount;
  53. if ((QCount = (queue->QPut - queue->QGet)) < 0)
  54. QCount += queue->QSize;
  55. return (queue->QSize - QCount - 1);
  56. }
  57. /*----------------------------------
  58. q_count - return number of chars in queue we can get.
  59. |----------------------------------*/
  60. int q_count(Queue *queue)
  61. {
  62. int QCount;
  63. if ((QCount = (queue->QPut - queue->QGet)) < 0)
  64. QCount += queue->QSize;
  65. return QCount;
  66. }
  67. /*--------------------------------------------------------------------------
  68. | q_get - Get bytes from queue.
  69. queue : our queue
  70. buf : buffer to put the data into
  71. Count : Max number of bytes to get
  72. Returns int value equal to number of bytes transferred.
  73. |--------------------------------------------------------------------------*/
  74. int q_get(Queue *queue, unsigned char *buf, int Count)
  75. {
  76. int get1, get2, ToMove;
  77. if ((ToMove = queue->QPut - queue->QGet) < 0)
  78. ToMove += queue->QSize; // adjust for wrap
  79. if (Count > ToMove) // only move whats asked
  80. {
  81. Count = ToMove;
  82. }
  83. if (Count == 0) // if nothing asked or nothing available
  84. return 0;
  85. get1 = queue->QSize - queue->QGet; // space till wrap point
  86. if (get1 < Count)
  87. {
  88. get2 = Count - get1; // two moves required
  89. }
  90. else // only one move required
  91. {
  92. get2 = 0;
  93. get1 = Count;
  94. }
  95. memcpy(buf, &queue->QBase[queue->QGet], get1);
  96. queue->QGet = (queue->QGet + get1) % queue->QSize;
  97. if (get2)
  98. {
  99. memcpy(&buf[get1], &queue->QBase[0], get2);
  100. queue->QGet = get2;
  101. }
  102. return Count;
  103. }
  104. /*--------------------------------------------------------------------------
  105. | q_put - Put data into the Queue.
  106. queue : our queue
  107. buf : buffer to get the data from
  108. Count : Max number of bytes to put
  109. Returns int value equal to number of bytes transferred.
  110. |--------------------------------------------------------------------------*/
  111. int q_put(Queue *queue, unsigned char *buf, int Count)
  112. {
  113. int put1, put2, room;
  114. if ((room = queue->QGet - queue->QPut - 1) < 0)
  115. room += queue->QSize; // adjust for wrap
  116. if (Count > room)
  117. Count = room;
  118. if (Count <= 0) // if nothing asked or nothing available
  119. return 0;
  120. put1 = queue->QSize - queue->QPut;
  121. if (put1 < Count)
  122. {
  123. put2 = Count - put1; // two moves required
  124. }
  125. else // only one move required
  126. {
  127. put2 = 0;
  128. put1 = Count;
  129. }
  130. memcpy(&queue->QBase[queue->QPut], buf, put1);
  131. queue->QPut = (queue->QPut + put1) % queue->QSize;
  132. if (put2)
  133. {
  134. memcpy(&queue->QBase[0], &buf[put1], put2);
  135. queue->QPut = put2;
  136. }
  137. return Count;
  138. }