f540d00679c8f6b3dc73779c902de10b8b11e656
[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 /*
41  * @implemented
42  */
43 VOID STDCALL
44 KeInitializeMutex(IN PKMUTEX Mutex,
45                   IN ULONG Level)
46 {
47   KeInitializeDispatcherHeader(&Mutex->Header,
48                                InternalMutexType,
49                                sizeof(KMUTEX) / sizeof(ULONG),
50                                1);
51   Mutex->MutantListEntry.Flink = NULL;
52   Mutex->MutantListEntry.Blink = NULL;
53   Mutex->OwnerThread = NULL;
54   Mutex->Abandoned = FALSE;
55   Mutex->ApcDisable = 1;
56 }
57
58 /*
59  * @implemented
60  */
61 LONG STDCALL
62 KeReadStateMutex(IN PKMUTEX Mutex)
63 {
64   return(Mutex->Header.SignalState);
65 }
66
67 /*
68  * @implemented
69  */
70 LONG STDCALL
71 KeReleaseMutex(IN PKMUTEX Mutex,
72                IN BOOLEAN Wait)
73 {
74   KeAcquireDispatcherDatabaseLock(Wait);
75   if (Mutex->OwnerThread != KeGetCurrentThread())
76     {
77       DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex);
78       KEBUGCHECK(0); /* THREAD_NOT_MUTEX_OWNER */
79     }
80   Mutex->Header.SignalState++;
81   assert(Mutex->Header.SignalState <= 1);
82   if (Mutex->Header.SignalState == 1)
83     {
84       Mutex->OwnerThread = NULL;
85       if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
86         RemoveEntryList(&Mutex->MutantListEntry);
87       KeDispatcherObjectWake(&Mutex->Header);
88     }
89   KeReleaseDispatcherDatabaseLock(Wait);
90   return(0);
91 }
92
93 /*
94  * @implemented
95  */
96 NTSTATUS STDCALL
97 KeWaitForMutexObject(IN PKMUTEX Mutex,
98                      IN KWAIT_REASON WaitReason,
99                      IN KPROCESSOR_MODE WaitMode,
100                      IN BOOLEAN Alertable,
101                      IN PLARGE_INTEGER Timeout)
102 {
103   return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
104 }
105
106
107 /*
108  * @implemented
109  */
110 VOID STDCALL
111 KeInitializeMutant(IN PKMUTANT Mutant,
112                    IN BOOLEAN InitialOwner)
113 {
114   if (InitialOwner == TRUE)
115     {
116       KeInitializeDispatcherHeader(&Mutant->Header,
117                                    InternalMutexType,
118                                    sizeof(KMUTANT) / sizeof(ULONG),
119                                    0);
120       InsertTailList(&KeGetCurrentThread()->MutantListHead,
121                      &Mutant->MutantListEntry);
122       Mutant->OwnerThread = KeGetCurrentThread();
123     }
124   else
125     {
126       KeInitializeDispatcherHeader(&Mutant->Header,
127                                    InternalMutexType,
128                                    sizeof(KMUTANT) / sizeof(ULONG),
129                                    1);
130       Mutant->MutantListEntry.Flink = NULL;
131       Mutant->MutantListEntry.Blink = NULL;
132       Mutant->OwnerThread = NULL;
133     }
134   Mutant->Abandoned = FALSE;
135   Mutant->ApcDisable = 0;
136 }
137
138 /*
139  * @implemented
140  */
141 LONG STDCALL
142 KeReadStateMutant(IN PKMUTANT Mutant)
143 {
144   return(Mutant->Header.SignalState);
145 }
146
147 /*
148  * @implemented
149  */
150 LONG STDCALL
151 KeReleaseMutant(IN PKMUTANT Mutant,
152                 IN KPRIORITY Increment,
153                 IN BOOLEAN Abandon,
154                 IN BOOLEAN Wait)
155 {
156   KeAcquireDispatcherDatabaseLock(Wait);
157   if (Abandon == FALSE)
158     {
159       if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread())
160         {
161           DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n",
162                    Mutant->OwnerThread,
163                    KeGetCurrentThread());
164           KEBUGCHECK(0); /* THREAD_NOT_MUTEX_OWNER */
165         }
166       Mutant->Header.SignalState++;
167       assert(Mutant->Header.SignalState <= 1);
168     }
169   else
170     {
171       if (Mutant->OwnerThread != NULL)
172         {
173           Mutant->Header.SignalState = 1;
174           Mutant->Abandoned = TRUE;
175         }
176     }
177
178   if (Mutant->Header.SignalState == 1)
179     {
180       Mutant->OwnerThread = NULL;
181       if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
182         RemoveEntryList(&Mutant->MutantListEntry);
183       KeDispatcherObjectWake(&Mutant->Header);
184     }
185
186   KeReleaseDispatcherDatabaseLock(Wait);
187   return(0);
188 }
189
190 /* EOF */