- KdDebuggerNotPresent should be FALSE by default.
[reactos.git] / reactos / ntoskrnl / ex / fmutex.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/fmutex.c
5 * PURPOSE: Implements fast mutexes
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #include <internal/debug.h>
13
14 VOID
15 FASTCALL
16 KiAcquireFastMutex(IN PFAST_MUTEX FastMutex);
17
18 /* FUNCTIONS *****************************************************************/
19
20 /*
21 * @implemented
22 */
23 VOID
24 FASTCALL
25 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
26 {
27 PKTHREAD Thread = KeGetCurrentThread();
28
29 /* Enter the Critical Region */
30 KeEnterCriticalRegion();
31 /*
32 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
33 (Thread == NULL) ||
34 (Thread->CombinedApcDisable != 0) ||
35 (Thread->Teb == NULL) ||
36 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
37 */
38 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
39 (Thread == NULL) ||
40 (Thread->CombinedApcDisable != 0));
41
42 ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
43
44 /* Decrease the count */
45 if (InterlockedDecrement(&FastMutex->Count))
46 {
47 /* Someone is still holding it, use slow path */
48 KiAcquireFastMutex(FastMutex);
49 }
50
51 /* Set the owner */
52 FastMutex->Owner = Thread;
53 }
54
55 /*
56 * @implemented
57 */
58 VOID
59 FASTCALL
60 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
61 {
62 /*
63 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
64 (KeGetCurrentThread() == NULL) ||
65 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
66 (KeGetCurrentThread()->Teb == NULL) ||
67 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
68
69 */
70 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
71 (KeGetCurrentThread() == NULL) ||
72 (KeGetCurrentThread()->CombinedApcDisable != 0));
73 ASSERT(FastMutex->Owner == KeGetCurrentThread());
74
75 /* Erase the owner */
76 FastMutex->Owner = NULL;
77
78 /* Increase the count */
79 if (InterlockedIncrement(&FastMutex->Count) <= 0)
80 {
81 /* Someone was waiting for it, signal the waiter */
82 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
83 }
84
85 /* Leave the critical region */
86 KeLeaveCriticalRegion();
87 }
88
89 /*
90 * @implemented
91 */
92 VOID
93 FASTCALL
94 ExAcquireFastMutex(PFAST_MUTEX FastMutex)
95 {
96 KIRQL OldIrql;
97 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
98
99 /* Raise IRQL to APC */
100 OldIrql = KfRaiseIrql(APC_LEVEL);
101
102 /* Decrease the count */
103 if (InterlockedDecrement(&FastMutex->Count))
104 {
105 /* Someone is still holding it, use slow path */
106 KiAcquireFastMutex(FastMutex);
107 }
108
109 /* Set the owner and IRQL */
110 FastMutex->Owner = KeGetCurrentThread();
111 FastMutex->OldIrql = OldIrql;
112 }
113
114 /*
115 * @implemented
116 */
117 VOID
118 FASTCALL
119 ExReleaseFastMutex (PFAST_MUTEX FastMutex)
120 {
121 KIRQL OldIrql;
122 ASSERT_IRQL(APC_LEVEL);
123
124 /* Erase the owner */
125 FastMutex->Owner = NULL;
126 OldIrql = FastMutex->OldIrql;
127
128 /* Increase the count */
129 if (InterlockedIncrement(&FastMutex->Count) <= 0)
130 {
131 /* Someone was waiting for it, signal the waiter */
132 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
133 }
134
135 /* Lower IRQL back */
136 KfLowerIrql(OldIrql);
137 }
138
139 /*
140 * @implemented
141 */
142 VOID
143 FASTCALL
144 ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
145 {
146 PKTHREAD Thread = KeGetCurrentThread();
147 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
148 (Thread == NULL) ||
149 (Thread->CombinedApcDisable != 0) ||
150 (Thread->Teb == NULL) ||
151 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
152 ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
153
154 /* Decrease the count */
155 if (InterlockedDecrement(&FastMutex->Count))
156 {
157 /* Someone is still holding it, use slow path */
158 KiAcquireFastMutex(FastMutex);
159 }
160
161 /* Set the owner */
162 FastMutex->Owner = Thread;
163 }
164
165 /*
166 * @implemented
167 */
168 VOID
169 FASTCALL
170 ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
171 {
172 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
173 (KeGetCurrentThread() == NULL) ||
174 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
175 (KeGetCurrentThread()->Teb == NULL) ||
176 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
177 ASSERT(FastMutex->Owner == KeGetCurrentThread());
178
179 /* Erase the owner */
180 FastMutex->Owner = NULL;
181
182 /* Increase the count */
183 if (InterlockedIncrement(&FastMutex->Count) <= 0)
184 {
185 /* Someone was waiting for it, signal the waiter */
186 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
187 }
188 }
189
190 /*
191 * @implemented
192 */
193 BOOLEAN
194 FASTCALL
195 ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
196 {
197 KIRQL OldIrql;
198 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
199
200 /* Raise to APC_LEVEL */
201 OldIrql = KfRaiseIrql(APC_LEVEL);
202
203 /* Check if we can quickly acquire it */
204 if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
205 {
206 /* We have, set us as owners */
207 FastMutex->Owner = KeGetCurrentThread();
208 FastMutex->OldIrql = OldIrql;
209 return TRUE;
210 }
211 else
212 {
213 /* Acquire attempt failed */
214 KfLowerIrql(OldIrql);
215 return FALSE;
216 }
217 }
218
219 /* EOF */