Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / ntoskrnl / ke / spinlock.c
1 /* $Id: spinlock.c,v 1.12 2002/09/07 15:12:57 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/spinlock.c
6 * PURPOSE: Implements spinlocks
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 3/6/98: Created
10 */
11
12 /*
13 * NOTE: On a uniprocessor machine spinlocks are implemented by raising
14 * the irq level
15 */
16
17 /* INCLUDES ****************************************************************/
18
19 #include <ntoskrnl.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24
25 /* FUNCTIONS ***************************************************************/
26
27 BOOLEAN STDCALL
28 KeSynchronizeExecution (PKINTERRUPT Interrupt,
29 PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
30 PVOID SynchronizeContext)
31 /*
32 * FUNCTION: Synchronizes the execution of a given routine with the ISR
33 * of a given interrupt object
34 * ARGUMENTS:
35 * Interrupt = Interrupt object to synchronize with
36 * SynchronizeRoutine = Routine to call whose execution is
37 * synchronized with the ISR
38 * SynchronizeContext = Parameter to pass to the synchronized routine
39 * RETURNS: TRUE if the operation succeeded
40 */
41 {
42 KIRQL oldlvl;
43 BOOLEAN ret;
44
45 KeRaiseIrql(Interrupt->SynchLevel,&oldlvl);
46 KeAcquireSpinLockAtDpcLevel(Interrupt->IrqLock);
47
48 ret = SynchronizeRoutine(SynchronizeContext);
49
50 KeReleaseSpinLockFromDpcLevel(Interrupt->IrqLock);
51 KeLowerIrql(oldlvl);
52
53 return(ret);
54 }
55
56 VOID STDCALL
57 KeInitializeSpinLock (PKSPIN_LOCK SpinLock)
58 /*
59 * FUNCTION: Initalizes a spinlock
60 * ARGUMENTS:
61 * SpinLock = Caller supplied storage for the spinlock
62 */
63 {
64 *SpinLock = 0;
65 }
66
67 VOID FASTCALL
68 KefAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
69 /*
70 * FUNCTION: Acquires a spinlock when the caller is already running at
71 * dispatch level
72 * ARGUMENTS:
73 * SpinLock = Spinlock to acquire
74 */
75 {
76 ULONG i;
77
78 /*
79 * FIXME: This depends on gcc assembling this test to a single load from
80 * the spinlock's value.
81 */
82 if ((ULONG)*SpinLock >= 2)
83 {
84 DbgPrint("Lock %x has bad value %x\n", SpinLock, *SpinLock);
85 KeBugCheck(0);
86 }
87
88 while ((i = InterlockedExchange(SpinLock, 1)) == 1)
89 {
90 #ifndef MP
91 DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
92 KeBugCheck(0);
93 #else /* not MP */
94 /* Avoid reading the value again too fast */
95 #endif /* MP */
96 }
97 }
98
99 #undef KeAcquireSpinLockAtDpcLevel
100
101 VOID STDCALL
102 KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock)
103 /*
104 * FUNCTION: Acquires a spinlock when the caller is already running at
105 * dispatch level
106 * ARGUMENTS:
107 * SpinLock = Spinlock to acquire
108 */
109 {
110 KefAcquireSpinLockAtDpcLevel (SpinLock);
111 }
112
113 VOID FASTCALL
114 KefReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
115 /*
116 * FUNCTION: Releases a spinlock when the caller was running at dispatch
117 * level before acquiring it
118 * ARGUMENTS:
119 * SpinLock = Spinlock to release
120 */
121 {
122 if (*SpinLock != 1)
123 {
124 DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
125 KeBugCheck(0);
126 }
127 (void)InterlockedExchange(SpinLock, 0);
128 }
129
130 #undef KeReleaseSpinLockFromDpcLevel
131
132 VOID STDCALL
133 KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock)
134 /*
135 * FUNCTION: Releases a spinlock when the caller was running at dispatch
136 * level before acquiring it
137 * ARGUMENTS:
138 * SpinLock = Spinlock to release
139 */
140 {
141 KefReleaseSpinLockFromDpcLevel (SpinLock);
142 }
143
144 /* EOF */