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.

243 lines
5.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: eventlst.cpp
  8. //
  9. // Contents: Microsoft Internet Security Trust Provider
  10. //
  11. // Functions: InitializeListLock
  12. // InitializeListEvent
  13. // LockWaitToWrite
  14. //
  15. // *** local functions ***
  16. // LockInitialize
  17. //
  18. // History: 29-May-1997 pberkman created
  19. //
  20. //--------------------------------------------------------------------------
  21. #include "global.hxx"
  22. #include "eventlst.h"
  23. #define PCB_LIST_DEBUG 0
  24. BOOL LockInitialize(LIST_LOCK *pListLock, DWORD dwDebugMask);
  25. BOOL InitializeListLock(LIST_LOCK *psListLock, DWORD dwDebugMask)
  26. {
  27. return(LockInitialize(psListLock, dwDebugMask));
  28. }
  29. BOOL InitializeListEvent(HANDLE *phListEvent)
  30. {
  31. if (!(*phListEvent = CreateEvent(NULL, TRUE, TRUE, NULL)))
  32. {
  33. return(FALSE);
  34. }
  35. return(TRUE);
  36. }
  37. BOOL EventFree(HANDLE hListEvent)
  38. {
  39. if ((hListEvent) && (hListEvent != INVALID_HANDLE_VALUE))
  40. {
  41. CloseHandle(hListEvent);
  42. return(TRUE);
  43. }
  44. return(FALSE);
  45. }
  46. BOOL LockInitialize(LIST_LOCK *pListLock, DWORD dwDebugMask)
  47. {
  48. //
  49. // Initialize the variable that indicates the number of
  50. // reader threads that are reading.
  51. // Initially no reader threads are reading.
  52. //
  53. pListLock->dwDebugMask = dwDebugMask;
  54. pListLock->NumReaders = 0;
  55. pListLock->hMutexNoWriter = CreateMutex(NULL, FALSE, NULL);
  56. if (!(pListLock->hMutexNoWriter))
  57. {
  58. return(FALSE);
  59. }
  60. //
  61. // Create the manual-reset event that is signalled when
  62. // no reader threads are reading. Initially no reader
  63. // threads are reading.
  64. //
  65. pListLock->hEventNoReaders = CreateEvent(NULL, TRUE, TRUE, NULL);
  66. if (pListLock->hEventNoReaders)
  67. {
  68. return(TRUE);
  69. }
  70. else
  71. {
  72. CloseHandle(pListLock->hMutexNoWriter);
  73. pListLock->hMutexNoWriter = NULL;
  74. return(FALSE);
  75. }
  76. }
  77. BOOL LockFree(LIST_LOCK *pListLock)
  78. {
  79. if (pListLock->hEventNoReaders)
  80. {
  81. CloseHandle(pListLock->hEventNoReaders);
  82. pListLock->hEventNoReaders = NULL;
  83. }
  84. if (pListLock->hMutexNoWriter)
  85. {
  86. CloseHandle(pListLock->hMutexNoWriter);
  87. pListLock->hMutexNoWriter = NULL;
  88. }
  89. return(TRUE);
  90. }
  91. void LockWaitToWrite(LIST_LOCK *pListLock)
  92. {
  93. //
  94. // We can write if the following are true:
  95. //
  96. // 1. The mutex guard is available and no
  97. // other threads are writing.
  98. //
  99. // 2. No threads are reading.
  100. //
  101. // Note that, unlike an rtl resource, this attempt
  102. // to write does not lock out other readers. We
  103. // just have to wait patiently for our turn.
  104. //
  105. HANDLE ahObjects[2];
  106. ahObjects[0] = pListLock->hMutexNoWriter;
  107. ahObjects[1] = pListLock->hEventNoReaders;
  108. WaitForMultipleObjects(2, ahObjects, TRUE, INFINITE);
  109. # if (DBG) && (PCB_LIST_DEBUG)
  110. DbgPrintf(pListLock->dwDebugMask, "Write Acquire: t:%04lX w:%p r:%p\n",
  111. GetCurrentThreadId(), ahObjects[0], ahObjects[1]);
  112. # endif
  113. //
  114. // Exit with the mutex, so as to prevent any more readers or writers
  115. // from coming in.
  116. //
  117. }
  118. void LockDoneWriting(LIST_LOCK *pListLock)
  119. {
  120. //
  121. // We're done writing, release the mutex so that
  122. // readers or other writers may come in.
  123. //
  124. # if (DBG) && (PCB_LIST_DEBUG)
  125. DbgPrintf(pListLock->dwDebugMask, "Write Release: t:%04lX w:%p r:%p\n",
  126. GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
  127. # endif
  128. ReleaseMutex(pListLock->hMutexNoWriter);
  129. }
  130. void LockWaitToRead(LIST_LOCK *pListLock)
  131. {
  132. //
  133. // Acquire the mutex that protects the list data.
  134. //
  135. WaitForSingleObject(pListLock->hMutexNoWriter, INFINITE);
  136. # if (DBG) && (PCB_LIST_DEBUG)
  137. DbgPrintf(pListLock->dwDebugMask, "Read Acquire: t:%04lX w:%p r:%p\n",
  138. GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
  139. # endif
  140. //
  141. // Now that we have the mutex, we can modify list data without
  142. // fear of corrupting anyone.
  143. //
  144. //
  145. // Increment the number of reader threads.
  146. //
  147. if (++pListLock->NumReaders == 1)
  148. {
  149. //
  150. // If this is the first reader thread, set our event to
  151. // reflect this. This is so that anyone waiting to write
  152. // will block until we're done.
  153. //
  154. ResetEvent(pListLock->hEventNoReaders);
  155. }
  156. //
  157. // Allow other writer/reader threads to use
  158. // the lock object.
  159. //
  160. ReleaseMutex(pListLock->hMutexNoWriter);
  161. }
  162. void LockDoneReading(LIST_LOCK *pListLock)
  163. {
  164. //
  165. // Acquire the mutex that guards the list data so we can
  166. // decrement the number of readers safely.
  167. //
  168. WaitForSingleObject(pListLock->hMutexNoWriter, INFINITE);
  169. # if (DBG) && (PCB_LIST_DEBUG)
  170. DbgPrintf(pListLock->dwDebugMask, "Read Release: t:%04lX w:%p r:%p\n",
  171. GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
  172. # endif
  173. if (--pListLock->NumReaders == 0)
  174. {
  175. //
  176. // We were the last reader. Wake up any potential
  177. // writers.
  178. //
  179. SetEvent(pListLock->hEventNoReaders);
  180. }
  181. //
  182. // Allow other writer/reader threads to use
  183. // the lock object.
  184. //
  185. ReleaseMutex(pListLock->hMutexNoWriter);
  186. }