1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: hal/halx86/generic/spinlock.c 5 * PURPOSE: Spinlock and Queued Spinlock Support 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 /* This file is compiled twice. Once for UP and once for MP */ 12 13 #include <hal.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 #include <internal/spinlock.h> 18 19 #undef KeAcquireSpinLock 20 #undef KeReleaseSpinLock 21 22 /* GLOBALS *******************************************************************/ 23 24 ULONG_PTR HalpSystemHardwareFlags; 25 KSPIN_LOCK HalpSystemHardwareLock; 26 27 /* FUNCTIONS *****************************************************************/ 28 29 #ifdef _M_IX86 30 31 /* 32 * @implemented 33 */ 34 KIRQL 35 FASTCALL 36 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock) 37 { 38 KIRQL OldIrql; 39 40 /* Raise to sync */ 41 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 42 43 /* Acquire the lock and return */ 44 KxAcquireSpinLock(SpinLock); 45 return OldIrql; 46 } 47 48 /* 49 * @implemented 50 */ 51 KIRQL 52 FASTCALL 53 KfAcquireSpinLock(PKSPIN_LOCK SpinLock) 54 { 55 KIRQL OldIrql; 56 57 /* Raise to dispatch and acquire the lock */ 58 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 59 KxAcquireSpinLock(SpinLock); 60 return OldIrql; 61 } 62 63 /* 64 * @implemented 65 */ 66 VOID 67 FASTCALL 68 KfReleaseSpinLock(PKSPIN_LOCK SpinLock, 69 KIRQL OldIrql) 70 { 71 /* Release the lock and lower IRQL back */ 72 KxReleaseSpinLock(SpinLock); 73 KeLowerIrql(OldIrql); 74 } 75 76 /* 77 * @implemented 78 */ 79 KIRQL 80 FASTCALL 81 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 82 { 83 KIRQL OldIrql; 84 85 /* Raise to dispatch */ 86 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 87 88 /* Acquire the lock */ 89 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 90 return OldIrql; 91 } 92 93 /* 94 * @implemented 95 */ 96 KIRQL 97 FASTCALL 98 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 99 { 100 KIRQL OldIrql; 101 102 /* Raise to synch */ 103 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 104 105 /* Acquire the lock */ 106 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 107 return OldIrql; 108 } 109 110 /* 111 * @implemented 112 */ 113 VOID 114 FASTCALL 115 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, 116 IN PKLOCK_QUEUE_HANDLE LockHandle) 117 { 118 /* Set up the lock */ 119 LockHandle->LockQueue.Next = NULL; 120 LockHandle->LockQueue.Lock = SpinLock; 121 122 /* Raise to dispatch */ 123 KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql); 124 125 /* Acquire the lock */ 126 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 127 } 128 129 /* 130 * @implemented 131 */ 132 VOID 133 FASTCALL 134 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, 135 IN PKLOCK_QUEUE_HANDLE LockHandle) 136 { 137 /* Set up the lock */ 138 LockHandle->LockQueue.Next = NULL; 139 LockHandle->LockQueue.Lock = SpinLock; 140 141 /* Raise to synch */ 142 KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql); 143 144 /* Acquire the lock */ 145 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 146 } 147 148 /* 149 * @implemented 150 */ 151 VOID 152 FASTCALL 153 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 154 IN KIRQL OldIrql) 155 { 156 /* Release the lock */ 157 KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 158 159 /* Lower IRQL back */ 160 KeLowerIrql(OldIrql); 161 } 162 163 /* 164 * @implemented 165 */ 166 VOID 167 FASTCALL 168 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle) 169 { 170 /* Simply lower IRQL back */ 171 KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK 172 KeLowerIrql(LockHandle->OldIrql); 173 } 174 175 #ifndef _MINIHAL_ 176 /* 177 * @implemented 178 */ 179 BOOLEAN 180 FASTCALL 181 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 182 IN PKIRQL OldIrql) 183 { 184 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock; 185 186 /* KM tests demonstrate that this raises IRQL even if locking fails */ 187 KeRaiseIrql(SYNCH_LEVEL, OldIrql); 188 /* HACK */ 189 return KeTryToAcquireSpinLockAtDpcLevel(Lock); 190 } 191 192 /* 193 * @implemented 194 */ 195 LOGICAL 196 FASTCALL 197 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 198 OUT PKIRQL OldIrql) 199 { 200 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock; 201 202 /* KM tests demonstrate that this raises IRQL even if locking fails */ 203 KeRaiseIrql(DISPATCH_LEVEL, OldIrql); 204 /* HACK */ 205 return KeTryToAcquireSpinLockAtDpcLevel(Lock); 206 } 207 #endif /* !defined(_MINIHAL_) */ 208 #endif /* defined(_M_IX86) */ 209 210 VOID 211 NTAPI 212 HalpAcquireCmosSpinLock(VOID) 213 { 214 ULONG_PTR Flags; 215 216 /* Get flags and disable interrupts */ 217 Flags = __readeflags(); 218 _disable(); 219 220 /* Acquire the lock */ 221 KxAcquireSpinLock(&HalpSystemHardwareLock); 222 223 /* We have the lock, save the flags now */ 224 HalpSystemHardwareFlags = Flags; 225 } 226 227 VOID 228 NTAPI 229 HalpReleaseCmosSpinLock(VOID) 230 { 231 ULONG_PTR Flags; 232 233 /* Get the flags */ 234 Flags = HalpSystemHardwareFlags; 235 236 /* Release the lock */ 237 KxReleaseSpinLock(&HalpSystemHardwareLock); 238 239 /* Restore the flags */ 240 __writeeflags(Flags); 241 } 242 243