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();
31 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
33 (Thread
->CombinedApcDisable
!= 0) ||
34 (Thread
->Teb
== NULL
) ||
35 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
36 ASSERT((Thread
== NULL
) || (FastMutex
->Owner
!= Thread
));
38 /* Decrease the count */
39 if (InterlockedDecrement(&FastMutex
->Count
))
41 /* Someone is still holding it, use slow path */
42 KiAcquireFastMutex(FastMutex
);
46 FastMutex
->Owner
= Thread
;
54 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex
)
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());
64 FastMutex
->Owner
= NULL
;
66 /* Increase the count */
67 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
69 /* Someone was waiting for it, signal the waiter */
70 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
73 /* Leave the critical region */
74 KeLeaveCriticalRegion();
82 ExAcquireFastMutex(PFAST_MUTEX FastMutex
)
85 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
87 /* Raise IRQL to APC */
88 OldIrql
= KfRaiseIrql(APC_LEVEL
);
90 /* Decrease the count */
91 if (InterlockedDecrement(&FastMutex
->Count
))
93 /* Someone is still holding it, use slow path */
94 KiAcquireFastMutex(FastMutex
);
97 /* Set the owner and IRQL */
98 FastMutex
->Owner
= KeGetCurrentThread();
99 FastMutex
->OldIrql
= OldIrql
;
107 ExReleaseFastMutex (PFAST_MUTEX FastMutex
)
110 ASSERT_IRQL(APC_LEVEL
);
112 /* Erase the owner */
113 FastMutex
->Owner
= NULL
;
114 OldIrql
= FastMutex
->OldIrql
;
116 /* Increase the count */
117 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
119 /* Someone was waiting for it, signal the waiter */
120 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
123 /* Lower IRQL back */
124 KfLowerIrql(OldIrql
);
132 ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex
)
134 PKTHREAD Thread
= KeGetCurrentThread();
135 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
137 (Thread
->CombinedApcDisable
!= 0) ||
138 (Thread
->Teb
== NULL
) ||
139 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
140 ASSERT((Thread
== NULL
) || (FastMutex
->Owner
!= Thread
));
142 /* Decrease the count */
143 if (InterlockedDecrement(&FastMutex
->Count
))
145 /* Someone is still holding it, use slow path */
146 KiAcquireFastMutex(FastMutex
);
150 FastMutex
->Owner
= Thread
;
158 ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex
)
160 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
161 (KeGetCurrentThread() == NULL
) ||
162 (KeGetCurrentThread()->CombinedApcDisable
!= 0) ||
163 (KeGetCurrentThread()->Teb
== NULL
) ||
164 (KeGetCurrentThread()->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
165 ASSERT(FastMutex
->Owner
== KeGetCurrentThread());
167 /* Erase the owner */
168 FastMutex
->Owner
= NULL
;
170 /* Increase the count */
171 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
173 /* Someone was waiting for it, signal the waiter */
174 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
183 ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex
)
186 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
188 /* Raise to APC_LEVEL */
189 OldIrql
= KfRaiseIrql(APC_LEVEL
);
191 /* Check if we can quickly acquire it */
192 if (InterlockedCompareExchange(&FastMutex
->Count
, 0, 1) == 1)
194 /* We have, set us as owners */
195 FastMutex
->Owner
= KeGetCurrentThread();
196 FastMutex
->OldIrql
= OldIrql
;
201 /* Acquire attempt failed */
202 KfLowerIrql(OldIrql
);