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 /* 176 * @implemented 177 */ 178 BOOLEAN 179 FASTCALL 180 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 181 IN PKIRQL OldIrql) 182 { 183 #ifdef CONFIG_SMP 184 ERROR_DBGBREAK("FIXME: Unused\n"); // FIXME: Unused 185 return FALSE; 186 #endif 187 188 /* Simply raise to synch */ 189 KeRaiseIrql(SYNCH_LEVEL, OldIrql); 190 191 /* Add an explicit memory barrier to prevent the compiler from reordering 192 memory accesses across the borders of spinlocks */ 193 KeMemoryBarrierWithoutFence(); 194 195 /* Always return true on UP Machines */ 196 return TRUE; 197 } 198 199 /* 200 * @implemented 201 */ 202 LOGICAL 203 FASTCALL 204 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 205 OUT PKIRQL OldIrql) 206 { 207 #ifdef CONFIG_SMP 208 ERROR_DBGBREAK("FIXME: Unused\n"); // FIXME: Unused 209 return FALSE; 210 #endif 211 212 /* Simply raise to dispatch */ 213 KeRaiseIrql(DISPATCH_LEVEL, OldIrql); 214 215 /* Add an explicit memory barrier to prevent the compiler from reordering 216 memory accesses across the borders of spinlocks */ 217 KeMemoryBarrierWithoutFence(); 218 219 /* Always return true on UP Machines */ 220 return TRUE; 221 } 222 223 #endif 224 225 VOID 226 NTAPI 227 HalpAcquireCmosSpinLock(VOID) 228 { 229 ULONG_PTR Flags; 230 231 /* Get flags and disable interrupts */ 232 Flags = __readeflags(); 233 _disable(); 234 235 /* Acquire the lock */ 236 KxAcquireSpinLock(&HalpSystemHardwareLock); 237 238 /* We have the lock, save the flags now */ 239 HalpSystemHardwareFlags = Flags; 240 } 241 242 VOID 243 NTAPI 244 HalpReleaseCmosSpinLock(VOID) 245 { 246 ULONG_PTR Flags; 247 248 /* Get the flags */ 249 Flags = HalpSystemHardwareFlags; 250 251 /* Release the lock */ 252 KxReleaseSpinLock(&HalpSystemHardwareLock); 253 254 /* Restore the flags */ 255 __writeeflags(Flags); 256 } 257 258