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 #ifdef _MINIHAL_ 32 VOID 33 FASTCALL 34 KefAcquireSpinLockAtDpcLevel( 35 IN PKSPIN_LOCK SpinLock) 36 { 37 #if DBG 38 /* To be on par with HAL/NTOSKRNL */ 39 *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1; 40 #endif 41 } 42 #endif /* defined(_MINIHAL_) */ 43 44 /* 45 * @implemented 46 */ 47 KIRQL 48 FASTCALL 49 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock) 50 { 51 KIRQL OldIrql; 52 53 /* Raise to sync */ 54 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 55 56 /* Acquire the lock and return */ 57 KxAcquireSpinLock(SpinLock); 58 return OldIrql; 59 } 60 61 /* 62 * @implemented 63 */ 64 KIRQL 65 FASTCALL 66 KfAcquireSpinLock(PKSPIN_LOCK SpinLock) 67 { 68 KIRQL OldIrql; 69 70 /* Raise to dispatch and acquire the lock */ 71 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 72 KxAcquireSpinLock(SpinLock); 73 return OldIrql; 74 } 75 76 /* 77 * @implemented 78 */ 79 VOID 80 FASTCALL 81 KfReleaseSpinLock(PKSPIN_LOCK SpinLock, 82 KIRQL OldIrql) 83 { 84 /* Release the lock and lower IRQL back */ 85 KxReleaseSpinLock(SpinLock); 86 KeLowerIrql(OldIrql); 87 } 88 89 /* 90 * @implemented 91 */ 92 KIRQL 93 FASTCALL 94 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 95 { 96 KIRQL OldIrql; 97 98 /* Raise to dispatch */ 99 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 100 101 /* Acquire the lock */ 102 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 103 return OldIrql; 104 } 105 106 /* 107 * @implemented 108 */ 109 KIRQL 110 FASTCALL 111 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 112 { 113 KIRQL OldIrql; 114 115 /* Raise to synch */ 116 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 117 118 /* Acquire the lock */ 119 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 120 return OldIrql; 121 } 122 123 /* 124 * @implemented 125 */ 126 VOID 127 FASTCALL 128 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, 129 IN PKLOCK_QUEUE_HANDLE LockHandle) 130 { 131 /* Set up the lock */ 132 LockHandle->LockQueue.Next = NULL; 133 LockHandle->LockQueue.Lock = SpinLock; 134 135 /* Raise to dispatch */ 136 KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql); 137 138 /* Acquire the lock */ 139 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 140 } 141 142 /* 143 * @implemented 144 */ 145 VOID 146 FASTCALL 147 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, 148 IN PKLOCK_QUEUE_HANDLE LockHandle) 149 { 150 /* Set up the lock */ 151 LockHandle->LockQueue.Next = NULL; 152 LockHandle->LockQueue.Lock = SpinLock; 153 154 /* Raise to synch */ 155 KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql); 156 157 /* Acquire the lock */ 158 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 159 } 160 161 /* 162 * @implemented 163 */ 164 VOID 165 FASTCALL 166 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 167 IN KIRQL OldIrql) 168 { 169 /* Release the lock */ 170 KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 171 172 /* Lower IRQL back */ 173 KeLowerIrql(OldIrql); 174 } 175 176 /* 177 * @implemented 178 */ 179 VOID 180 FASTCALL 181 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle) 182 { 183 /* Simply lower IRQL back */ 184 KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK 185 KeLowerIrql(LockHandle->OldIrql); 186 } 187 188 #ifndef _MINIHAL_ 189 /* 190 * @implemented 191 */ 192 BOOLEAN 193 FASTCALL 194 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 195 IN PKIRQL OldIrql) 196 { 197 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock; 198 199 /* KM tests demonstrate that this raises IRQL even if locking fails */ 200 KeRaiseIrql(SYNCH_LEVEL, OldIrql); 201 /* HACK */ 202 return KeTryToAcquireSpinLockAtDpcLevel(Lock); 203 } 204 205 /* 206 * @implemented 207 */ 208 LOGICAL 209 FASTCALL 210 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 211 OUT PKIRQL OldIrql) 212 { 213 PKSPIN_LOCK Lock = KeGetCurrentPrcb()->LockQueue[LockNumber].Lock; 214 215 /* KM tests demonstrate that this raises IRQL even if locking fails */ 216 KeRaiseIrql(DISPATCH_LEVEL, OldIrql); 217 /* HACK */ 218 return KeTryToAcquireSpinLockAtDpcLevel(Lock); 219 } 220 #endif /* !defined(_MINIHAL_) */ 221 222 #endif /* defined(_M_IX86) */ 223 224 VOID 225 NTAPI 226 HalpAcquireCmosSpinLock(VOID) 227 { 228 ULONG_PTR Flags; 229 230 /* Get flags and disable interrupts */ 231 Flags = __readeflags(); 232 _disable(); 233 234 /* Acquire the lock */ 235 KxAcquireSpinLock(&HalpSystemHardwareLock); 236 237 /* We have the lock, save the flags now */ 238 HalpSystemHardwareFlags = Flags; 239 } 240 241 VOID 242 NTAPI 243 HalpReleaseCmosSpinLock(VOID) 244 { 245 ULONG_PTR Flags; 246 247 /* Get the flags */ 248 Flags = HalpSystemHardwareFlags; 249 250 /* Release the lock */ 251 KxReleaseSpinLock(&HalpSystemHardwareLock); 252 253 /* Restore the flags */ 254 __writeeflags(Flags); 255 } 256 257