1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ke/amd64/spinlock.c 5 * PURPOSE: Spinlock and Queued Spinlock Support 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #undef KeAcquireSpinLock 16 #undef KeReleaseSpinLock 17 18 /* FUNCTIONS *****************************************************************/ 19 20 /* 21 * @implemented 22 */ 23 KIRQL 24 KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock) 25 { 26 KIRQL OldIrql; 27 28 /* Raise to sync */ 29 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 30 31 /* Acquire the lock and return */ 32 KxAcquireSpinLock(SpinLock); 33 return OldIrql; 34 } 35 36 /* 37 * @implemented 38 */ 39 KIRQL 40 NTAPI 41 KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock) 42 { 43 KIRQL OldIrql; 44 45 /* Raise to dispatch */ 46 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 47 48 /* Acquire the lock and return */ 49 KxAcquireSpinLock(SpinLock); 50 return OldIrql; 51 } 52 53 /* 54 * @implemented 55 */ 56 VOID 57 NTAPI 58 KeReleaseSpinLock(PKSPIN_LOCK SpinLock, 59 KIRQL OldIrql) 60 { 61 /* Release the lock and lower IRQL back */ 62 KxReleaseSpinLock(SpinLock); 63 KeLowerIrql(OldIrql); 64 } 65 66 /* 67 * @implemented 68 */ 69 KIRQL 70 KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 71 { 72 KIRQL OldIrql; 73 74 /* Raise to dispatch */ 75 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 76 77 /* Acquire the lock */ 78 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 79 return OldIrql; 80 } 81 82 /* 83 * @implemented 84 */ 85 KIRQL 86 KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) 87 { 88 KIRQL OldIrql; 89 90 /* Raise to synch */ 91 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 92 93 /* Acquire the lock */ 94 KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 95 return OldIrql; 96 } 97 98 /* 99 * @implemented 100 */ 101 VOID 102 KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, 103 IN PKLOCK_QUEUE_HANDLE LockHandle) 104 { 105 /* Set up the lock */ 106 LockHandle->LockQueue.Next = NULL; 107 LockHandle->LockQueue.Lock = SpinLock; 108 109 /* Raise to dispatch */ 110 KeRaiseIrql(DISPATCH_LEVEL, &LockHandle->OldIrql); 111 112 /* Acquire the lock */ 113 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 114 } 115 116 117 /* 118 * @implemented 119 */ 120 VOID 121 KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, 122 IN PKLOCK_QUEUE_HANDLE LockHandle) 123 { 124 /* Set up the lock */ 125 LockHandle->LockQueue.Next = NULL; 126 LockHandle->LockQueue.Lock = SpinLock; 127 128 /* Raise to synch */ 129 KeRaiseIrql(SYNCH_LEVEL, &LockHandle->OldIrql); 130 131 /* Acquire the lock */ 132 KxAcquireSpinLock(LockHandle->LockQueue.Lock); // HACK 133 } 134 135 136 /* 137 * @implemented 138 */ 139 VOID 140 KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 141 IN KIRQL OldIrql) 142 { 143 /* Release the lock */ 144 KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK 145 146 /* Lower IRQL back */ 147 KeLowerIrql(OldIrql); 148 } 149 150 151 /* 152 * @implemented 153 */ 154 VOID 155 KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle) 156 { 157 /* Simply lower IRQL back */ 158 KxReleaseSpinLock(LockHandle->LockQueue.Lock); // HACK 159 KeLowerIrql(LockHandle->OldIrql); 160 } 161 162 163 /* 164 * @implemented 165 */ 166 BOOLEAN 167 KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 168 IN PKIRQL OldIrql) 169 { 170 #ifndef CONFIG_SMP 171 /* Simply raise to dispatch */ 172 KeRaiseIrql(DISPATCH_LEVEL, OldIrql); 173 174 /* Add an explicit memory barrier to prevent the compiler from reordering 175 memory accesses across the borders of spinlocks */ 176 KeMemoryBarrierWithoutFence(); 177 178 /* Always return true on UP Machines */ 179 return TRUE; 180 #else 181 UNIMPLEMENTED; 182 ASSERT(FALSE); 183 #endif 184 } 185 186 /* 187 * @implemented 188 */ 189 LOGICAL 190 KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, 191 OUT PKIRQL OldIrql) 192 { 193 #ifndef CONFIG_SMP 194 /* Simply raise to dispatch */ 195 KeRaiseIrql(DISPATCH_LEVEL, OldIrql); 196 197 /* Add an explicit memory barrier to prevent the compiler from reordering 198 memory accesses across the borders of spinlocks */ 199 KeMemoryBarrierWithoutFence(); 200 201 /* Always return true on UP Machines */ 202 return TRUE; 203 #else 204 UNIMPLEMENTED; 205 ASSERT(FALSE); 206 #endif 207 } 208 209 /* EOF */ 210