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.

90 lines
2.2 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. locks.c
  5. Abstract:
  6. Millennium locks. See below for details of the WHY you might
  7. do this.
  8. Author:
  9. Scott Holden (sholden) 2/10/2000
  10. Revision History:
  11. --*/
  12. #include "tcpipbase.h"
  13. //
  14. // The TCP/IP stacks makes a number of assumptions about the receive indication
  15. // path being at DPC. Since Millennium indicates receives up on a global event
  16. // at PASSIVE level, we need to take extra precautions in this path to return
  17. // the thread to the correct IRQL upon releasing a spin lock.
  18. //
  19. // Since TCP/IP will grab locks and release in a different order and in some
  20. // situations CTEGetLockAtDPC will not save the previous IRQL, there were many
  21. // issues with leaving threads at the wrong IRQL when enabling spin locks.
  22. //
  23. // This implementation solves this issue -- since we are on a uniproc machine.
  24. // When we enter the first lock, we can raise IRQL to DISPATCH to ensure
  25. // that we are not pre-empted. Each additional lock will increment the count.
  26. // When the last lock is released, the old IRQL is restored.
  27. //
  28. //
  29. LONG gTcpipLock = 0;
  30. KIRQL gTcpipOldIrql;
  31. VOID
  32. TcpipMillenGetLock(
  33. CTELock *pLock
  34. )
  35. {
  36. #if DBG
  37. KIRQL OldIrql;
  38. #endif // DBG
  39. ASSERT(gTcpipLock >= 0);
  40. // First spinlock acquire raises DPC.
  41. if (gTcpipLock++ == 0) {
  42. KeRaiseIrql(DISPATCH_LEVEL, &gTcpipOldIrql);
  43. }
  44. // Verify that our individual locks are somehow not reentrant.
  45. // KeAcquireSpinLock will do that for us on Millennium.
  46. ASSERT((KeAcquireSpinLock(pLock, &OldIrql),OldIrql==DISPATCH_LEVEL) && ((*pLock)&1));
  47. ASSERT(gTcpipLock >= 1);
  48. return;
  49. }
  50. VOID
  51. TcpipMillenFreeLock(
  52. CTELock *pLock
  53. )
  54. {
  55. ASSERT(gTcpipLock >= 1);
  56. // Verify that our individual locks are somehow not reentrant.
  57. // KeReleaseSpinLock on Millennium does that and more for us.
  58. ASSERT(KeGetCurrentIrql()==DISPATCH_LEVEL &&
  59. (KeReleaseSpinLock(pLock, DISPATCH_LEVEL),TRUE));
  60. // Last release lowers IRQL to original.
  61. if (--gTcpipLock == 0) {
  62. KeLowerIrql(gTcpipOldIrql);
  63. }
  64. ASSERT(gTcpipLock >= 0);
  65. return;
  66. }