@implemented and @unimplemented comments for ntoskrnl/ke/*.c
[reactos.git] / reactos / 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: mutex.c,v 1.13 2003/07/10 17:44:06 royce Exp $
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 */