tpl.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. tpl.c
  5. Abstract:
  6. This module implements core Task Priority Level services for UEFI firmware.
  7. Author:
  8. Evan Green 28-Feb-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "ueficore.h"
  16. //
  17. // ---------------------------------------------------------------- Definitions
  18. //
  19. //
  20. // ------------------------------------------------------ Data Type Definitions
  21. //
  22. //
  23. // ----------------------------------------------- Internal Function Prototypes
  24. //
  25. //
  26. // -------------------------------------------------------------------- Globals
  27. //
  28. //
  29. // Define the current TPL.
  30. //
  31. EFI_TPL EfiCurrentTpl = TPL_APPLICATION;
  32. //
  33. // Remember whether or not interrupts were enabled when the raise function
  34. // disabled them.
  35. //
  36. BOOLEAN EfiTplInterruptsWereEnabled;
  37. //
  38. // ------------------------------------------------------------------ Functions
  39. //
  40. EFIAPI
  41. EFI_TPL
  42. EfiCoreRaiseTpl (
  43. EFI_TPL NewTpl
  44. )
  45. /*++
  46. Routine Description:
  47. This routine raises the current Task Priority Level.
  48. Arguments:
  49. NewTpl - Supplies the new TPL to set.
  50. Return Value:
  51. Returns the previous TPL.
  52. --*/
  53. {
  54. EFI_TPL OldTpl;
  55. OldTpl = EfiCurrentTpl;
  56. if ((NewTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) {
  57. EfiTplInterruptsWereEnabled = EfiDisableInterrupts();
  58. }
  59. EfiCurrentTpl = NewTpl;
  60. return OldTpl;
  61. }
  62. EFIAPI
  63. VOID
  64. EfiCoreRestoreTpl (
  65. EFI_TPL OldTpl
  66. )
  67. /*++
  68. Routine Description:
  69. This routine restores the Task Priority Level back to its original value
  70. before it was raised.
  71. Arguments:
  72. OldTpl - Supplies the original TPL to restore back to.
  73. Return Value:
  74. None.
  75. --*/
  76. {
  77. EFI_TPL PreviousTpl;
  78. PreviousTpl = EfiCurrentTpl;
  79. ASSERT(OldTpl <= PreviousTpl);
  80. ASSERT(OldTpl <= TPL_HIGH_LEVEL);
  81. //
  82. // If for some reason the TPL was above high and is going below high, set
  83. // it directly to high.
  84. //
  85. if ((PreviousTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) {
  86. PreviousTpl = TPL_HIGH_LEVEL;
  87. EfiCurrentTpl = TPL_HIGH_LEVEL;
  88. }
  89. //
  90. // Dispatch pending events.
  91. //
  92. while (((-2 << OldTpl) & EfiEventsPending) != 0) {
  93. EfiCurrentTpl = (UINTN)EfiCoreFindHighBitSet64(EfiEventsPending);
  94. if ((EfiCurrentTpl < TPL_HIGH_LEVEL) &&
  95. (PreviousTpl >= TPL_HIGH_LEVEL)) {
  96. if (EfiTplInterruptsWereEnabled != FALSE) {
  97. EfiEnableInterrupts();
  98. }
  99. }
  100. PreviousTpl = EfiCurrentTpl;
  101. EfiCoreDispatchEventNotifies(EfiCurrentTpl);
  102. }
  103. //
  104. // Set the new value. If the TPL is crossing below high,
  105. //
  106. EfiCurrentTpl = OldTpl;
  107. if ((PreviousTpl >= TPL_HIGH_LEVEL) && (OldTpl < TPL_HIGH_LEVEL)) {
  108. if (EfiTplInterruptsWereEnabled != FALSE) {
  109. EfiEnableInterrupts();
  110. }
  111. }
  112. return;
  113. }
  114. //
  115. // --------------------------------------------------------- Internal Functions
  116. //