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