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)
9 /* INCLUDES *****************************************************************/
12 #include <internal/debug.h>
16 KiAcquireFastMutex(IN PFAST_MUTEX FastMutex
);
18 /* FUNCTIONS *****************************************************************/
25 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex
)
27 PKTHREAD Thread
= KeGetCurrentThread();
29 /* Enter the Critical Region */
30 KeEnterCriticalRegion();
32 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
34 (Thread->CombinedApcDisable != 0) ||
35 (Thread->Teb == NULL) ||
36 (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
38 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
40 (Thread
->CombinedApcDisable
!= 0));
42 ASSERT((Thread
== NULL
) || (FastMutex
->Owner
!= Thread
));
44 /* Decrease the count */
45 if (InterlockedDecrement(&FastMutex
->Count
))
47 /* Someone is still holding it, use slow path */
48 KiAcquireFastMutex(FastMutex
);
52 FastMutex
->Owner
= Thread
;
60 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex
)
63 ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
64 (KeGetCurrentThread() == NULL) ||
65 (KeGetCurrentThread()->CombinedApcDisable != 0) ||
66 (KeGetCurrentThread()->Teb == NULL) ||
67 (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
70 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
71 (KeGetCurrentThread() == NULL
) ||
72 (KeGetCurrentThread()->CombinedApcDisable
!= 0));
73 ASSERT(FastMutex
->Owner
== KeGetCurrentThread());
76 FastMutex
->Owner
= NULL
;
78 /* Increase the count */
79 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
81 /* Someone was waiting for it, signal the waiter */
82 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
85 /* Leave the critical region */
86 KeLeaveCriticalRegion();
94 ExAcquireFastMutex(PFAST_MUTEX FastMutex
)
97 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
99 /* Raise IRQL to APC */
100 OldIrql
= KfRaiseIrql(APC_LEVEL
);
102 /* Decrease the count */
103 if (InterlockedDecrement(&FastMutex
->Count
))
105 /* Someone is still holding it, use slow path */
106 KiAcquireFastMutex(FastMutex
);
109 /* Set the owner and IRQL */
110 FastMutex
->Owner
= KeGetCurrentThread();
111 FastMutex
->OldIrql
= OldIrql
;
119 ExReleaseFastMutex (PFAST_MUTEX FastMutex
)
122 ASSERT_IRQL(APC_LEVEL
);
124 /* Erase the owner */
125 FastMutex
->Owner
= NULL
;
126 OldIrql
= FastMutex
->OldIrql
;
128 /* Increase the count */
129 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
131 /* Someone was waiting for it, signal the waiter */
132 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
135 /* Lower IRQL back */
136 KfLowerIrql(OldIrql
);
144 ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex
)
146 PKTHREAD Thread
= KeGetCurrentThread();
147 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
149 (Thread
->CombinedApcDisable
!= 0) ||
150 (Thread
->Teb
== NULL
) ||
151 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
152 ASSERT((Thread
== NULL
) || (FastMutex
->Owner
!= Thread
));
154 /* Decrease the count */
155 if (InterlockedDecrement(&FastMutex
->Count
))
157 /* Someone is still holding it, use slow path */
158 KiAcquireFastMutex(FastMutex
);
162 FastMutex
->Owner
= Thread
;
170 ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex
)
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());
179 /* Erase the owner */
180 FastMutex
->Owner
= NULL
;
182 /* Increase the count */
183 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
185 /* Someone was waiting for it, signal the waiter */
186 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
195 ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex
)
198 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
200 /* Raise to APC_LEVEL */
201 OldIrql
= KfRaiseIrql(APC_LEVEL
);
203 /* Check if we can quickly acquire it */
204 if (InterlockedCompareExchange(&FastMutex
->Count
, 0, 1) == 1)
206 /* We have, set us as owners */
207 FastMutex
->Owner
= KeGetCurrentThread();
208 FastMutex
->OldIrql
= OldIrql
;
213 /* Acquire attempt failed */
214 KfLowerIrql(OldIrql
);