c29f7cee2b805c5516cb7f92ff83156689252e2a
[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 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
32 (Thread == NULL) ||
33 (Thread->CombinedApcDisable != 0) ||
34 (Thread->Teb == NULL) ||
35 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
36 ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
37
38 /* Decrease the count */
39 if (InterlockedDecrement(&FastMutex->Count))
40 {
41 /* Someone is still holding it, use slow path */
42 KiAcquireFastMutex(FastMutex);
43 }
44
45 /* Set the owner */
46 FastMutex->Owner = Thread;
47 }
48
49 /*
50 * @implemented
51 */
52 VOID
53 FASTCALL
54 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
55 {
56 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
57 (KeGetCurrentThread() == NULL) ||
58 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
59 (KeGetCurrentThread()->Teb == NULL) ||
60 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
61 ASSERT(FastMutex->Owner == KeGetCurrentThread());
62
63 /* Erase the owner */
64 FastMutex->Owner = NULL;
65
66 /* Increase the count */
67 if (InterlockedIncrement(&FastMutex->Count) <= 0)
68 {
69 /* Someone was waiting for it, signal the waiter */
70 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
71 }
72
73 /* Leave the critical region */
74 KeLeaveCriticalRegion();
75 }
76
77 /*
78 * @implemented
79 */
80 VOID
81 FASTCALL
82 ExAcquireFastMutex(PFAST_MUTEX FastMutex)
83 {
84 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
85 KIRQL OldIrql;
86
87 /* Raise IRQL to APC */
88 OldIrql = KfRaiseIrql(APC_LEVEL);
89
90 /* Decrease the count */
91 if (InterlockedDecrement(&FastMutex->Count))
92 {
93 /* Someone is still holding it, use slow path */
94 KiAcquireFastMutex(FastMutex);
95 }
96
97 /* Set the owner and IRQL */
98 FastMutex->Owner = KeGetCurrentThread();
99 FastMutex->OldIrql = OldIrql;
100 }
101
102 /*
103 * @implemented
104 */
105 VOID
106 FASTCALL
107 ExReleaseFastMutex (PFAST_MUTEX FastMutex)
108 {
109 ASSERT_IRQL(APC_LEVEL);
110
111 /* Erase the owner */
112 FastMutex->Owner = NULL;
113
114 /* Increase the count */
115 if (InterlockedIncrement(&FastMutex->Count) <= 0)
116 {
117 /* Someone was waiting for it, signal the waiter */
118 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
119 }
120
121 /* Lower IRQL back */
122 KfLowerIrql(FastMutex->OldIrql);
123 }
124
125 /*
126 * @implemented
127 */
128 VOID
129 FASTCALL
130 ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
131 {
132 PKTHREAD Thread = KeGetCurrentThread();
133 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
134 (Thread == NULL) ||
135 (Thread->CombinedApcDisable != 0) ||
136 (Thread->Teb == NULL) ||
137 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
138 ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
139
140 /* Decrease the count */
141 if (InterlockedDecrement(&FastMutex->Count))
142 {
143 /* Someone is still holding it, use slow path */
144 KiAcquireFastMutex(FastMutex);
145 }
146
147 /* Set the owner */
148 FastMutex->Owner = Thread;
149 }
150
151 /*
152 * @implemented
153 */
154 VOID
155 FASTCALL
156 ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
157 {
158 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
159 (KeGetCurrentThread() == NULL) ||
160 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
161 (KeGetCurrentThread()->Teb == NULL) ||
162 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
163 ASSERT(FastMutex->Owner == KeGetCurrentThread());
164
165 /* Erase the owner */
166 FastMutex->Owner = NULL;
167
168 /* Increase the count */
169 if (InterlockedIncrement(&FastMutex->Count) <= 0)
170 {
171 /* Someone was waiting for it, signal the waiter */
172 KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
173 }
174 }
175
176 /*
177 * @implemented
178 */
179 BOOLEAN
180 FASTCALL
181 ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
182 {
183 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
184 KIRQL OldIrql;
185
186 /* Raise to APC_LEVEL */
187 OldIrql = KfRaiseIrql(APC_LEVEL);
188
189 /* Check if we can quickly acquire it */
190 if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
191 {
192 /* We have, set us as owners */
193 FastMutex->Owner = KeGetCurrentThread();
194 return TRUE;
195 }
196 else
197 {
198 /* Acquire attempt failed */
199 KfLowerIrql(OldIrql);
200 return FALSE;
201 }
202 }
203
204 /* EOF */