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
)
109 ASSERT_IRQL(APC_LEVEL
);
111 /* Erase the owner */
112 FastMutex
->Owner
= NULL
;
114 /* Increase the count */
115 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
117 /* Someone was waiting for it, signal the waiter */
118 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
121 /* Lower IRQL back */
122 KfLowerIrql(FastMutex
->OldIrql
);
130 ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex
)
132 PKTHREAD Thread
= KeGetCurrentThread();
133 ASSERT((KeGetCurrentIrql() == APC_LEVEL
) ||
135 (Thread
->CombinedApcDisable
!= 0) ||
136 (Thread
->Teb
== NULL
) ||
137 (Thread
->Teb
>= (PTEB
)MM_SYSTEM_RANGE_START
));
138 ASSERT((Thread
== NULL
) || (FastMutex
->Owner
!= Thread
));
140 /* Decrease the count */
141 if (InterlockedDecrement(&FastMutex
->Count
))
143 /* Someone is still holding it, use slow path */
144 KiAcquireFastMutex(FastMutex
);
148 FastMutex
->Owner
= Thread
;
156 ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex
)
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());
165 /* Erase the owner */
166 FastMutex
->Owner
= NULL
;
168 /* Increase the count */
169 if (InterlockedIncrement(&FastMutex
->Count
) <= 0)
171 /* Someone was waiting for it, signal the waiter */
172 KeSetEventBoostPriority(&FastMutex
->Gate
, IO_NO_INCREMENT
);
181 ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex
)
184 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
186 /* Raise to APC_LEVEL */
187 OldIrql
= KfRaiseIrql(APC_LEVEL
);
189 /* Check if we can quickly acquire it */
190 if (InterlockedCompareExchange(&FastMutex
->Count
, 0, 1) == 1)
192 /* We have, set us as owners */
193 FastMutex
->Owner
= KeGetCurrentThread();
198 /* Acquire attempt failed */
199 KfLowerIrql(OldIrql
);