ExRaiseStatus() is now fatal back again as SEH is not needed for valid ops
[reactos.git] / ntoskrnl / ke / mutex.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:         ReactOS kernel
22  * FILE:            ntoskrnl/ke/mutex.c
23  * PURPOSE:         Implements mutex
24  * PROGRAMMER:      David Welch (welch@mcmail.com)
25  * UPDATE HISTORY:
26  *                  Created 22/05/98
27  */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <internal/ke.h>
33 #include <internal/ps.h>
34 #include <internal/id.h>
35
36 #include <internal/debug.h>
37
38 /* FUNCTIONS *****************************************************************/
39
40 #ifndef LIBCAPTIVE
41
42 VOID STDCALL
43 KeInitializeMutex(IN PKMUTEX Mutex,
44                   IN ULONG Level)
45 {
46   KeInitializeDispatcherHeader(&Mutex->Header,
47                                InternalMutexType,
48                                sizeof(KMUTEX) / sizeof(ULONG),
49                                1);
50   Mutex->MutantListEntry.Flink = NULL;
51   Mutex->MutantListEntry.Blink = NULL;
52   Mutex->OwnerThread = NULL;
53   Mutex->Abandoned = FALSE;
54   Mutex->ApcDisable = 1;
55 }
56
57 LONG STDCALL
58 KeReadStateMutex(IN PKMUTEX Mutex)
59 {
60   return(Mutex->Header.SignalState);
61 }
62
63 LONG STDCALL
64 KeReleaseMutex(IN PKMUTEX Mutex,
65                IN BOOLEAN Wait)
66 {
67   KeAcquireDispatcherDatabaseLock(Wait);
68   if (Mutex->OwnerThread != KeGetCurrentThread())
69     {
70       DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex);
71       KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */
72     }
73   Mutex->Header.SignalState++;
74   assert(Mutex->Header.SignalState <= 1);
75   if (Mutex->Header.SignalState == 1)
76     {
77       Mutex->OwnerThread = NULL;
78       if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
79         RemoveEntryList(&Mutex->MutantListEntry);
80       KeDispatcherObjectWake(&Mutex->Header);
81     }
82   KeReleaseDispatcherDatabaseLock(Wait);
83   return(0);
84 }
85
86 NTSTATUS STDCALL
87 KeWaitForMutexObject(IN PKMUTEX Mutex,
88                      IN KWAIT_REASON WaitReason,
89                      IN KPROCESSOR_MODE WaitMode,
90                      IN BOOLEAN Alertable,
91                      IN PLARGE_INTEGER Timeout)
92 {
93   return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
94 }
95
96 #endif /* LIBCAPTIVE */
97
98 VOID STDCALL
99 KeInitializeMutant(IN PKMUTANT Mutant,
100                    IN BOOLEAN InitialOwner)
101 {
102   if (InitialOwner == TRUE)
103     {
104       KeInitializeDispatcherHeader(&Mutant->Header,
105                                    InternalMutexType,
106                                    sizeof(KMUTANT) / sizeof(ULONG),
107                                    0);
108       InsertTailList(&KeGetCurrentThread()->MutantListHead,
109                      &Mutant->MutantListEntry);
110       Mutant->OwnerThread = KeGetCurrentThread();
111     }
112   else
113     {
114       KeInitializeDispatcherHeader(&Mutant->Header,
115                                    InternalMutexType,
116                                    sizeof(KMUTANT) / sizeof(ULONG),
117                                    1);
118       Mutant->MutantListEntry.Flink = NULL;
119       Mutant->MutantListEntry.Blink = NULL;
120       Mutant->OwnerThread = NULL;
121     }
122   Mutant->Abandoned = FALSE;
123   Mutant->ApcDisable = 0;
124 }
125
126 #ifndef LIBCAPTIVE
127
128 LONG STDCALL
129 KeReadStateMutant(IN PKMUTANT Mutant)
130 {
131   return(Mutant->Header.SignalState);
132 }
133
134 #endif /* LIBCAPTIVE */
135
136 LONG STDCALL
137 KeReleaseMutant(IN PKMUTANT Mutant,
138                 IN KPRIORITY Increment,
139                 IN BOOLEAN Abandon,
140                 IN BOOLEAN Wait)
141 {
142   KeAcquireDispatcherDatabaseLock(Wait);
143   if (Abandon == FALSE)
144     {
145       if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread())
146         {
147           DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n",
148                    Mutant->OwnerThread,
149                    KeGetCurrentThread());
150           KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */
151         }
152       if (Mutant->Header.SignalState==0)
153         {
154           Mutant->Header.SignalState++;
155         }
156       else
157         {
158           /* ntfs.sys behaviour: KeInitializeMutant(,FALSE); KeReleaseMutant(,0,FALSE,FALSE;
159            * Ugh.
160            */
161           DbgPrint("WARNING: Releasing already unlocked KMUTANT %p CurrentThread %p !!!\n",
162                    Mutant,KeGetCurrentThread());
163         }
164       assert(Mutant->Header.SignalState <= 1);
165     }
166   else
167     {
168       if (Mutant->OwnerThread != NULL)
169         {
170           Mutant->Header.SignalState = 1;
171           Mutant->Abandoned = TRUE;
172         }
173     }
174
175   if (Mutant->Header.SignalState == 1)
176     {
177       Mutant->OwnerThread = NULL;
178       if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
179         RemoveEntryList(&Mutant->MutantListEntry);
180 #ifndef LIBCAPTIVE
181       KeDispatcherObjectWake(&Mutant->Header);
182 #endif /* LIBCAPTIVE */
183     }
184
185   KeReleaseDispatcherDatabaseLock(Wait);
186   return(0);
187 }
188
189 /* EOF */