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.

115 lines
3.0 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. win32simplelock.c
  5. Abstract:
  6. works downlevel to Win95/NT3.
  7. The only dependencies are InterlocedIncrement, IncrementDecrement, Sleep.
  8. The old Interlocked semantics are good enough.
  9. can be statically initialized, but not with all zeros.
  10. never runs out of memory
  11. does not wait or boost-upon-exit efficiently.
  12. must be held for only short periods of time.
  13. should perhaps be called spinlock
  14. can be taken recursively.
  15. can only be taken exclusively, NOT reader/writer.
  16. acquire has a "SleepCount" parameter:
  17. 0 is like TryEnterCriticalSection
  18. INFINITE is like EnterCriticalSection
  19. SHOULD have a spincount to scale hot locks on multiprocs
  20. Author:
  21. Jay Krell (JayKrell) August 2001
  22. Revision History:
  23. --*/
  24. #include "windows.h"
  25. #include "win32simplelock.h"
  26. DWORD
  27. Win32AcquireSimpleLock(PWIN32_SIMPLE_LOCK Lock, DWORD SleepCount)
  28. {
  29. DWORD Result = 0;
  30. BOOL IncrementedWaiters = FALSE;
  31. // ASSERT(Lock->Size != 0);
  32. Retry:
  33. if (InterlockedIncrement(&Lock->Lock) == 0)
  34. {
  35. //
  36. // I got it.
  37. //
  38. Lock->OwnerThreadId = GetCurrentThreadId();
  39. if (Lock->EntryCount == 0)
  40. {
  41. Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_FIRST_ACQUIRE;
  42. }
  43. if (Lock->EntryCount+1 != 0) /* avoid rollover */
  44. Lock->EntryCount += 1;
  45. if (IncrementedWaiters)
  46. InterlockedDecrement(&Lock->Waiters);
  47. Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_NOT_RECURSIVE_ACQUIRE;
  48. return Result;
  49. }
  50. else if (Lock->OwnerThreadId == GetCurrentThreadId())
  51. {
  52. //
  53. // I got it recursively.
  54. //
  55. Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_RECURSIVE_ACQUIRE;
  56. return Result;
  57. }
  58. InterlockedDecrement(&Lock->Lock);
  59. if (SleepCount == 0)
  60. return 0;
  61. //
  62. // Someone else has it, wait for them to finish.
  63. //
  64. if (!IncrementedWaiters)
  65. {
  66. InterlockedIncrement(&Lock->Waiters);
  67. IncrementedWaiters = TRUE;
  68. }
  69. if (SleepCount == INFINITE)
  70. {
  71. while (Lock->OwnerThreadId != 0)
  72. Sleep(0);
  73. }
  74. else
  75. {
  76. while (Lock->OwnerThreadId != 0 && SleepCount--)
  77. Sleep(0);
  78. }
  79. goto Retry;
  80. }
  81. DWORD
  82. Win32ReleaseSimpleLock(PWIN32_SIMPLE_LOCK Lock)
  83. {
  84. // ASSERT(Lock->Size != 0);
  85. DWORD Result = 0;
  86. if (InterlockedDecrement(&Lock->Lock) < 0)
  87. {
  88. // I'm done with it (recursively).
  89. Lock->OwnerThreadId = 0;
  90. // Give any waiters a slightly better chance than me.
  91. // This is "racy", but that's ok.
  92. if (Lock->Waiters != 0)
  93. Sleep(0);
  94. Result |= WIN32_RELEASE_SIMPLE_LOCK_WAS_NOT_RECURSIVE_RELEASE;
  95. }
  96. else
  97. {
  98. Result |= WIN32_RELEASE_SIMPLE_LOCK_WAS_RECURSIVE_RELEASE;
  99. }
  100. return Result;
  101. }