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.

333 lines
7.9 KiB

  1. //============================================================================
  2. // Copyright (c) 1996, Microsoft Corporation
  3. //
  4. // File: sync.c
  5. //
  6. // History:
  7. // Abolade Gbadegesin Jan-12-1996 Created.
  8. //
  9. // Synchronization routines used by IPRIP.
  10. //============================================================================
  11. #include "pchrip.h"
  12. //----------------------------------------------------------------------------
  13. // Function: QueueRipWorker
  14. //
  15. // This function is called to queue a RIP function in a safe fashion;
  16. // if cleanup is in progress or if RIP has stopped, this function
  17. // discards the work-item.
  18. //----------------------------------------------------------------------------
  19. DWORD
  20. QueueRipWorker(
  21. WORKERFUNCTION pFunction,
  22. PVOID pContext
  23. ) {
  24. DWORD dwErr = NO_ERROR;
  25. EnterCriticalSection(&ig.IG_CS);
  26. if (ig.IG_Status != IPRIP_STATUS_RUNNING) {
  27. //
  28. // cannot queue a work function when RIP has quit or is quitting
  29. //
  30. dwErr = ERROR_CAN_NOT_COMPLETE;
  31. }
  32. else {
  33. BOOL bSuccess;
  34. ++ig.IG_ActivityCount;
  35. bSuccess = QueueUserWorkItem(
  36. (LPTHREAD_START_ROUTINE)pFunction,
  37. pContext, 0
  38. );
  39. if (!bSuccess) {
  40. dwErr = GetLastError();
  41. --ig.IG_ActivityCount;
  42. }
  43. }
  44. LeaveCriticalSection(&ig.IG_CS);
  45. return dwErr;
  46. }
  47. //----------------------------------------------------------------------------
  48. // Function: EnterRipAPI
  49. //
  50. // This function is called to when entering a RIP api, as well as
  51. // when entering the input thread and timer thread.
  52. // It checks to see if RIP has stopped, and if so it quits; otherwise
  53. // it increments the count of active threads.
  54. //----------------------------------------------------------------------------
  55. BOOL
  56. EnterRipAPI(
  57. ) {
  58. BOOL bEntered;
  59. EnterCriticalSection(&ig.IG_CS);
  60. if (ig.IG_Status == IPRIP_STATUS_RUNNING) {
  61. //
  62. // RIP is running, so the API may continue
  63. //
  64. ++ig.IG_ActivityCount;
  65. bEntered = TRUE;
  66. }
  67. else {
  68. //
  69. // RIP is not running, so the API exits quietly
  70. //
  71. bEntered = FALSE;
  72. }
  73. LeaveCriticalSection(&ig.IG_CS);
  74. return bEntered;
  75. }
  76. //----------------------------------------------------------------------------
  77. // Function: EnterRipWorker
  78. //
  79. // This function is called when entering a RIP worker-function.
  80. // Since there is a lapse between the time a worker-function is queued
  81. // and the time the function is actually invoked by a worker thread,
  82. // this function must check to see if RIP has stopped or is stopping;
  83. // if this is the case, then it decrements the activity count,
  84. // releases the activity semaphore, and quits.
  85. //----------------------------------------------------------------------------
  86. BOOL
  87. EnterRipWorker(
  88. ) {
  89. BOOL bEntered;
  90. EnterCriticalSection(&ig.IG_CS);
  91. if (ig.IG_Status == IPRIP_STATUS_RUNNING) {
  92. //
  93. // RIP is running, so the function may continue
  94. //
  95. bEntered = TRUE;
  96. }
  97. else
  98. if (ig.IG_Status == IPRIP_STATUS_STOPPING) {
  99. //
  100. // RIP is not running, but it was, so the function must stop.
  101. //
  102. --ig.IG_ActivityCount;
  103. ReleaseSemaphore(ig.IG_ActivitySemaphore, 1, NULL);
  104. bEntered = FALSE;
  105. }
  106. else {
  107. //
  108. // RIP probably never started. quit quietly
  109. //
  110. bEntered = FALSE;
  111. }
  112. LeaveCriticalSection(&ig.IG_CS);
  113. return bEntered;
  114. }
  115. //----------------------------------------------------------------------------
  116. // Function: LeaveRipWorker
  117. //
  118. // This function is called when leaving a RIP API or worker function.
  119. // It decrements the activity count, and if it detects that RIP has stopped
  120. // or is stopping, it releases the activity semaphore.
  121. //----------------------------------------------------------------------------
  122. VOID
  123. LeaveRipWorker(
  124. ) {
  125. EnterCriticalSection(&ig.IG_CS);
  126. --ig.IG_ActivityCount;
  127. if (ig.IG_Status == IPRIP_STATUS_STOPPING) {
  128. ReleaseSemaphore(ig.IG_ActivitySemaphore, 1, NULL);
  129. }
  130. LeaveCriticalSection(&ig.IG_CS);
  131. }
  132. //----------------------------------------------------------------------------
  133. // Function: CreateReadWriteLock
  134. //
  135. // Initializes a multiple-reader/single-writer lock object
  136. //----------------------------------------------------------------------------
  137. DWORD
  138. CreateReadWriteLock(
  139. PREAD_WRITE_LOCK pRWL
  140. ) {
  141. pRWL->RWL_ReaderCount = 0;
  142. try {
  143. InitializeCriticalSection(&(pRWL)->RWL_ReadWriteBlock);
  144. }
  145. except (EXCEPTION_EXECUTE_HANDLER) {
  146. return GetLastError();
  147. }
  148. pRWL->RWL_ReaderDoneEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  149. if (pRWL->RWL_ReaderDoneEvent != NULL) {
  150. return GetLastError();
  151. }
  152. return NO_ERROR;
  153. }
  154. //----------------------------------------------------------------------------
  155. // Function: DeleteReadWriteLock
  156. //
  157. // Frees resources used by a multiple-reader/single-writer lock object
  158. //----------------------------------------------------------------------------
  159. VOID
  160. DeleteReadWriteLock(
  161. PREAD_WRITE_LOCK pRWL
  162. ) {
  163. CloseHandle(pRWL->RWL_ReaderDoneEvent);
  164. pRWL->RWL_ReaderDoneEvent = NULL;
  165. DeleteCriticalSection(&pRWL->RWL_ReadWriteBlock);
  166. pRWL->RWL_ReaderCount = 0;
  167. }
  168. //----------------------------------------------------------------------------
  169. // Function: AcquireReadLock
  170. //
  171. // Secures shared ownership of the lock object for the caller.
  172. //
  173. // readers enter the read-write critical section, increment the count,
  174. // and leave the critical section
  175. //----------------------------------------------------------------------------
  176. VOID
  177. AcquireReadLock(
  178. PREAD_WRITE_LOCK pRWL
  179. ) {
  180. EnterCriticalSection(&pRWL->RWL_ReadWriteBlock);
  181. InterlockedIncrement(&pRWL->RWL_ReaderCount);
  182. LeaveCriticalSection(&pRWL->RWL_ReadWriteBlock);
  183. }
  184. //----------------------------------------------------------------------------
  185. // Function: ReleaseReadLock
  186. //
  187. // Relinquishes shared ownership of the lock object.
  188. //
  189. // the last reader sets the event to wake any waiting writers
  190. //----------------------------------------------------------------------------
  191. VOID
  192. ReleaseReadLock(
  193. PREAD_WRITE_LOCK pRWL
  194. ) {
  195. if (InterlockedDecrement(&pRWL->RWL_ReaderCount) < 0) {
  196. SetEvent(pRWL->RWL_ReaderDoneEvent);
  197. }
  198. }
  199. //----------------------------------------------------------------------------
  200. // Function: AcquireWriteLock
  201. //
  202. // Secures exclusive ownership of the lock object.
  203. //
  204. // the writer blocks other threads by entering the ReadWriteBlock section,
  205. // and then waits for any thread(s) owning the lock to finish
  206. //----------------------------------------------------------------------------
  207. VOID
  208. AcquireWriteLock(
  209. PREAD_WRITE_LOCK pRWL
  210. ) {
  211. EnterCriticalSection(&pRWL->RWL_ReadWriteBlock);
  212. if (InterlockedDecrement(&pRWL->RWL_ReaderCount) >= 0) {
  213. WaitForSingleObject(pRWL->RWL_ReaderDoneEvent, INFINITE);
  214. }
  215. }
  216. //----------------------------------------------------------------------------
  217. // Function: ReleaseWriteLock
  218. //
  219. // Relinquishes exclusive ownership of the lock object.
  220. //
  221. // the writer releases the lock by setting the count to zero
  222. // and then leaving the ReadWriteBlock critical section
  223. //----------------------------------------------------------------------------
  224. VOID
  225. ReleaseWriteLock(
  226. PREAD_WRITE_LOCK pRWL
  227. ) {
  228. pRWL->RWL_ReaderCount = 0;
  229. LeaveCriticalSection(&(pRWL)->RWL_ReadWriteBlock);
  230. }