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.

241 lines
5.1 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. notify.cxx
  5. Abstract:
  6. This module implements notification lists.
  7. Author:
  8. Michael Courage (mcourage) 25-Jan-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text( PAGE, UlAddNotifyEntry )
  14. #pragma alloc_text( PAGE, UlRemoveNotifyEntry )
  15. #pragma alloc_text( PAGE, UlNotifyAllEntries )
  16. #endif // ALLOC_PRAGMA
  17. #if 0
  18. NOT PAGEABLE -- UlInitializeNotifyHead
  19. NOT PAGEABLE -- UlInitializeNotifyEntry
  20. #endif
  21. //
  22. // Public functions.
  23. //
  24. /***************************************************************************++
  25. Routine Description:
  26. Initializes the head of the list.
  27. Arguments:
  28. pHead - pointer to the head of list structure
  29. pResource - an optional pointer to a resource to synchronize access
  30. --***************************************************************************/
  31. VOID
  32. UlInitializeNotifyHead(
  33. IN PUL_NOTIFY_HEAD pHead,
  34. IN PUL_ERESOURCE pResource
  35. )
  36. {
  37. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  38. ASSERT(pHead);
  39. InitializeListHead(&pHead->ListHead);
  40. pHead->pResource = pResource;
  41. }
  42. /***************************************************************************++
  43. Routine Description:
  44. Initializes an entry in a notify list.
  45. Arguments:
  46. pEntry - the entry to be initialized
  47. pHost - A void context pointer assumed to be the containing object
  48. --***************************************************************************/
  49. VOID
  50. UlInitializeNotifyEntry(
  51. IN PUL_NOTIFY_ENTRY pEntry,
  52. IN PVOID pHost
  53. )
  54. {
  55. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  56. ASSERT(pEntry);
  57. ASSERT(pHost);
  58. pEntry->ListEntry.Flink = pEntry->ListEntry.Blink = NULL;
  59. pEntry->pHead = NULL;
  60. pEntry->pHost = pHost;
  61. }
  62. /***************************************************************************++
  63. Routine Description:
  64. Adds an entry to the tail of the list.
  65. Arguments:
  66. pHead - Head of the target list
  67. pEntry - the entry to be added to the list
  68. --***************************************************************************/
  69. VOID
  70. UlAddNotifyEntry(
  71. IN PUL_NOTIFY_HEAD pHead,
  72. IN PUL_NOTIFY_ENTRY pEntry
  73. )
  74. {
  75. PAGED_CODE();
  76. ASSERT(pEntry);
  77. ASSERT(pHead);
  78. ASSERT(pEntry->pHead == NULL);
  79. ASSERT(pEntry->ListEntry.Flink == NULL);
  80. if (pHead->pResource) {
  81. UlAcquireResourceExclusive(pHead->pResource, TRUE);
  82. }
  83. pEntry->pHead = pHead;
  84. InsertTailList(&pHead->ListHead, &pEntry->ListEntry);
  85. if (pHead->pResource) {
  86. UlReleaseResource(pHead->pResource);
  87. }
  88. }
  89. /***************************************************************************++
  90. Routine Description:
  91. Removes an entry from the notify list it is on.
  92. Arguments:
  93. pEntry - the entry to be removed
  94. --***************************************************************************/
  95. VOID
  96. UlRemoveNotifyEntry(
  97. IN PUL_NOTIFY_ENTRY pEntry
  98. )
  99. {
  100. PUL_NOTIFY_HEAD pHead;
  101. PAGED_CODE();
  102. ASSERT(pEntry);
  103. pHead = pEntry->pHead;
  104. if (pHead) {
  105. ASSERT(pEntry->ListEntry.Flink);
  106. if (pHead->pResource) {
  107. UlAcquireResourceExclusive(pHead->pResource, TRUE);
  108. }
  109. pEntry->pHead = NULL;
  110. RemoveEntryList(&pEntry->ListEntry);
  111. pEntry->ListEntry.Flink = pEntry->ListEntry.Blink = NULL;
  112. if (pHead->pResource) {
  113. UlReleaseResource(pHead->pResource);
  114. }
  115. }
  116. }
  117. /***************************************************************************++
  118. Routine Description:
  119. An internal iterator that applies pFunction to every element in the
  120. list.
  121. We start at the head of the list, and keep iterating until we get to
  122. the end OR pFunction returns FALSE.
  123. Arguments:
  124. pFunction - the function to call for each member of the list
  125. pHead - the head of the list over which we'll iterate
  126. pv - an arbitrary context pointer that will be passed to pFunction
  127. --***************************************************************************/
  128. VOID
  129. UlNotifyAllEntries(
  130. IN PUL_NOTIFY_FUNC pFunction,
  131. IN PUL_NOTIFY_HEAD pHead,
  132. IN PVOID pv
  133. )
  134. {
  135. PLIST_ENTRY pEntry;
  136. PUL_NOTIFY_ENTRY pNotifyEntry;
  137. PLIST_ENTRY pNextEntry;
  138. BOOLEAN Continue;
  139. PAGED_CODE();
  140. ASSERT(pHead);
  141. // grab the resource
  142. if (pHead->pResource) {
  143. UlAcquireResourceExclusive(pHead->pResource, TRUE);
  144. }
  145. //
  146. // Iterate through the list
  147. //
  148. pEntry = pHead->ListHead.Flink;
  149. Continue = TRUE;
  150. while (Continue && (pEntry != &pHead->ListHead)) {
  151. ASSERT(pEntry);
  152. pNotifyEntry = CONTAINING_RECORD(
  153. pEntry,
  154. UL_NOTIFY_ENTRY,
  155. ListEntry
  156. );
  157. pEntry = pEntry->Flink;
  158. //
  159. // Call the notification function
  160. //
  161. Continue = pFunction(
  162. pNotifyEntry,
  163. pNotifyEntry->pHost,
  164. pv
  165. );
  166. }
  167. // let go of the resource
  168. if (pHead->pResource) {
  169. UlReleaseResource(pHead->pResource);
  170. }
  171. }