Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmutex.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ke/mutex.c 00005 * PURPOSE: Implements the Mutant Dispatcher Object 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* FUNCTIONS *****************************************************************/ 00016 00017 /* 00018 * @implemented 00019 */ 00020 VOID 00021 NTAPI 00022 KeInitializeMutant(IN PKMUTANT Mutant, 00023 IN BOOLEAN InitialOwner) 00024 { 00025 PKTHREAD CurrentThread; 00026 KIRQL OldIrql; 00027 00028 /* Check if we have an initial owner */ 00029 if (InitialOwner) 00030 { 00031 /* We also need to associate a thread */ 00032 CurrentThread = KeGetCurrentThread(); 00033 Mutant->OwnerThread = CurrentThread; 00034 00035 /* We're about to touch the Thread, so lock the Dispatcher */ 00036 OldIrql = KiAcquireDispatcherLock(); 00037 00038 /* And insert it into its list */ 00039 InsertTailList(&CurrentThread->MutantListHead, 00040 &Mutant->MutantListEntry); 00041 00042 /* Release Dispatcher Lock */ 00043 KiReleaseDispatcherLock(OldIrql); 00044 } 00045 else 00046 { 00047 /* In this case, we don't have an owner yet */ 00048 Mutant->OwnerThread = NULL; 00049 } 00050 00051 /* Now we set up the Dispatcher Header */ 00052 Mutant->Header.Type = MutantObject; 00053 Mutant->Header.Size = sizeof(KMUTANT) / sizeof(ULONG); 00054 Mutant->Header.DpcActive = FALSE; 00055 Mutant->Header.SignalState = InitialOwner ? 0 : 1; 00056 InitializeListHead(&(Mutant->Header.WaitListHead)); 00057 00058 /* Initialize the default data */ 00059 Mutant->Abandoned = FALSE; 00060 Mutant->ApcDisable = 0; 00061 } 00062 00063 /* 00064 * @implemented 00065 */ 00066 VOID 00067 NTAPI 00068 KeInitializeMutex(IN PKMUTEX Mutex, 00069 IN ULONG Level) 00070 { 00071 /* Set up the Dispatcher Header */ 00072 Mutex->Header.Type = MutantObject; 00073 Mutex->Header.Size = sizeof(KMUTEX) / sizeof(ULONG); 00074 Mutex->Header.DpcActive = FALSE; 00075 Mutex->Header.SignalState = 1; 00076 InitializeListHead(&(Mutex->Header.WaitListHead)); 00077 00078 /* Initialize the default data */ 00079 Mutex->OwnerThread = NULL; 00080 Mutex->Abandoned = FALSE; 00081 Mutex->ApcDisable = 1; 00082 } 00083 00084 /* 00085 * @implemented 00086 */ 00087 LONG 00088 NTAPI 00089 KeReadStateMutant(IN PKMUTANT Mutant) 00090 { 00091 /* Return the Signal State */ 00092 return Mutant->Header.SignalState; 00093 } 00094 00095 /* 00096 * @implemented 00097 */ 00098 LONG 00099 NTAPI 00100 KeReleaseMutant(IN PKMUTANT Mutant, 00101 IN KPRIORITY Increment, 00102 IN BOOLEAN Abandon, 00103 IN BOOLEAN Wait) 00104 { 00105 KIRQL OldIrql; 00106 LONG PreviousState; 00107 PKTHREAD CurrentThread = KeGetCurrentThread(); 00108 BOOLEAN EnableApc = FALSE; 00109 ASSERT_MUTANT(Mutant); 00110 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); 00111 00112 /* Lock the Dispatcher Database */ 00113 OldIrql = KiAcquireDispatcherLock(); 00114 00115 /* Save the Previous State */ 00116 PreviousState = Mutant->Header.SignalState; 00117 00118 /* Check if it is to be abandonned */ 00119 if (Abandon == FALSE) 00120 { 00121 /* Make sure that the Owner Thread is the current Thread */ 00122 if (Mutant->OwnerThread != CurrentThread) 00123 { 00124 /* Release the lock */ 00125 KiReleaseDispatcherLock(OldIrql); 00126 00127 /* Raise an exception */ 00128 ExRaiseStatus(Mutant->Abandoned ? STATUS_ABANDONED : 00129 STATUS_MUTANT_NOT_OWNED); 00130 } 00131 00132 /* If the thread owns it, then increase the signal state */ 00133 Mutant->Header.SignalState++; 00134 } 00135 else 00136 { 00137 /* It's going to be abandonned */ 00138 Mutant->Header.SignalState = 1; 00139 Mutant->Abandoned = TRUE; 00140 } 00141 00142 /* Check if the signal state is only single */ 00143 if (Mutant->Header.SignalState == 1) 00144 { 00145 /* Check if it's below 0 now */ 00146 if (PreviousState <= 0) 00147 { 00148 /* Remove the mutant from the list */ 00149 RemoveEntryList(&Mutant->MutantListEntry); 00150 00151 /* Save if we need to re-enable APCs */ 00152 EnableApc = Mutant->ApcDisable; 00153 } 00154 00155 /* Remove the Owning Thread and wake it */ 00156 Mutant->OwnerThread = NULL; 00157 00158 /* Check if the Wait List isn't empty */ 00159 if (!IsListEmpty(&Mutant->Header.WaitListHead)) 00160 { 00161 /* Wake the Mutant */ 00162 KiWaitTest(&Mutant->Header, Increment); 00163 } 00164 } 00165 00166 /* Check if the caller wants to wait after this release */ 00167 if (Wait == FALSE) 00168 { 00169 /* Release the Lock */ 00170 KiReleaseDispatcherLock(OldIrql); 00171 } 00172 else 00173 { 00174 /* Set a wait */ 00175 CurrentThread->WaitNext = TRUE; 00176 CurrentThread->WaitIrql = OldIrql; 00177 } 00178 00179 /* Check if we need to re-enable APCs */ 00180 if (EnableApc) KeLeaveCriticalRegion(); 00181 00182 /* Return the previous state */ 00183 return PreviousState; 00184 } 00185 00186 /* 00187 * @implemented 00188 */ 00189 LONG 00190 NTAPI 00191 KeReleaseMutex(IN PKMUTEX Mutex, 00192 IN BOOLEAN Wait) 00193 { 00194 ASSERT_MUTANT(Mutex); 00195 00196 /* There's no difference at this level between the two */ 00197 return KeReleaseMutant(Mutex, 1, FALSE, Wait); 00198 } 00199 00200 /* EOF */ Generated on Sat May 26 2012 04:36:20 for ReactOS by
1.7.6.1
|