Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mutntobj.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 mutntobj.c 00008 00009 Abstract: 00010 00011 This module implements the kernel mutant object. Functions are 00012 provided to initialize, read, and release mutant objects. 00013 00014 N.B. Kernel mutex objects have been subsumed by mutant objects. 00015 00016 Author: 00017 00018 David N. Cutler (davec) 16-Oct-1989 00019 00020 Environment: 00021 00022 Kernel mode only. 00023 00024 Revision History: 00025 00026 --*/ 00027 00028 #include "ki.h" 00029 00030 // 00031 // The following assert macro is used to check that an input mutant is 00032 // really a kmutant and not something else, like deallocated pool. 00033 // 00034 00035 #define ASSERT_MUTANT(E) { \ 00036 ASSERT((E)->Header.Type == MutantObject); \ 00037 } 00038 00039 VOID 00040 KeInitializeMutant ( 00041 IN PRKMUTANT Mutant, 00042 IN BOOLEAN InitialOwner 00043 ) 00044 00045 /*++ 00046 00047 Routine Description: 00048 00049 This function initializes a kernel mutant object. 00050 00051 Arguments: 00052 00053 Mutant - Supplies a pointer to a dispatcher object of type mutant. 00054 00055 InitialOwner - Supplies a boolean value that determines whether the 00056 current thread is to be the initial owner of the mutant object. 00057 00058 Return Value: 00059 00060 None. 00061 00062 --*/ 00063 00064 { 00065 00066 PLIST_ENTRY ListEntry; 00067 KIRQL OldIrql; 00068 PRKTHREAD Thread; 00069 00070 // 00071 // Initialize standard dispatcher object header, set the owner thread to 00072 // NULL, set the abandoned state to FALSE, and set the APC disable count 00073 // to zero (this is the only thing that distinguishes a mutex from a mutant). 00074 // 00075 00076 Mutant->Header.Type = MutantObject; 00077 Mutant->Header.Size = sizeof(KMUTANT) / sizeof(LONG); 00078 if (InitialOwner == TRUE) { 00079 Thread = KeGetCurrentThread(); 00080 Mutant->Header.SignalState = 0; 00081 Mutant->OwnerThread = Thread; 00082 KiLockDispatcherDatabase(&OldIrql); 00083 ListEntry = Thread->MutantListHead.Blink; 00084 InsertHeadList(ListEntry, &Mutant->MutantListEntry); 00085 KiUnlockDispatcherDatabase(OldIrql); 00086 00087 } else { 00088 Mutant->Header.SignalState = 1; 00089 Mutant->OwnerThread = (PKTHREAD)NULL; 00090 } 00091 00092 InitializeListHead(&Mutant->Header.WaitListHead); 00093 Mutant->Abandoned = FALSE; 00094 Mutant->ApcDisable = 0; 00095 return; 00096 } 00097 00098 VOID 00099 KeInitializeMutex ( 00100 IN PRKMUTANT Mutant, 00101 IN ULONG Level 00102 ) 00103 00104 /*++ 00105 00106 Routine Description: 00107 00108 This function initializes a kernel mutex object. The level number 00109 is ignored. 00110 00111 N.B. Kernel mutex objects have been subsumed by mutant objects. 00112 00113 Arguments: 00114 00115 Mutex - Supplies a pointer to a dispatcher object of type mutex. 00116 00117 Level - Ignored. 00118 00119 Return Value: 00120 00121 None. 00122 00123 --*/ 00124 00125 { 00126 00127 PLIST_ENTRY ListEntry; 00128 00129 // 00130 // Initialize standard dispatcher object header, set the owner thread to 00131 // NULL, set the abandoned state to FALSE, adn set the APC disable count 00132 // to one (this is the only thing that distinguishes a mutex from a mutant). 00133 // 00134 00135 Mutant->Header.Type = MutantObject; 00136 Mutant->Header.Size = sizeof(KMUTANT) / sizeof(LONG); 00137 Mutant->Header.SignalState = 1; 00138 InitializeListHead(&Mutant->Header.WaitListHead); 00139 Mutant->OwnerThread = (PKTHREAD)NULL; 00140 Mutant->Abandoned = FALSE; 00141 Mutant->ApcDisable = 1; 00142 return; 00143 } 00144 00145 LONG 00146 KeReadStateMutant ( 00147 IN PRKMUTANT Mutant 00148 ) 00149 00150 /*++ 00151 00152 Routine Description: 00153 00154 This function reads the current signal state of a mutant object. 00155 00156 Arguments: 00157 00158 Mutant - Supplies a pointer to a dispatcher object of type mutant. 00159 00160 Return Value: 00161 00162 The current signal state of the mutant object. 00163 00164 --*/ 00165 00166 { 00167 00168 ASSERT_MUTANT(Mutant); 00169 00170 // 00171 // Return current signal state of mutant object. 00172 // 00173 00174 return Mutant->Header.SignalState; 00175 } 00176 00177 LONG 00178 KeReleaseMutant ( 00179 IN PRKMUTANT Mutant, 00180 IN KPRIORITY Increment, 00181 IN BOOLEAN Abandoned, 00182 IN BOOLEAN Wait 00183 ) 00184 00185 /*++ 00186 00187 Routine Description: 00188 00189 This function releases a mutant object by incrementing the mutant 00190 count. If the resultant value is one, then an attempt is made to 00191 satisfy as many Waits as possible. The previous signal state of 00192 the mutant is returned as the function value. If the Abandoned 00193 parameter is TRUE, then the mutant object is released by settings 00194 the signal state to one. 00195 00196 Arguments: 00197 00198 Mutant - Supplies a pointer to a dispatcher object of type mutant. 00199 00200 Increment - Supplies the priority increment that is to be applied 00201 if setting the event causes a Wait to be satisfied. 00202 00203 Abandoned - Supplies a boolean value that signifies whether the 00204 mutant object is being abandoned. 00205 00206 Wait - Supplies a boolean value that signifies whether the call to 00207 KeReleaseMutant will be immediately followed by a call to one 00208 of the kernel Wait functions. 00209 00210 Return Value: 00211 00212 The previous signal state of the mutant object. 00213 00214 --*/ 00215 00216 { 00217 00218 KIRQL OldIrql; 00219 LONG OldState; 00220 PRKTHREAD Thread; 00221 00222 00223 ASSERT_MUTANT(Mutant); 00224 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00225 00226 // 00227 // Raise IRQL to dispatcher level and lock dispatcher database. 00228 // 00229 00230 KiLockDispatcherDatabase(&OldIrql); 00231 00232 // 00233 // Capture the current signal state of the mutant object. 00234 // 00235 00236 OldState = Mutant->Header.SignalState; 00237 00238 // 00239 // If the Abandoned parameter is TRUE, then force the release of the 00240 // mutant object by setting its ownership count to one and setting its 00241 // abandoned state to TRUE. Otherwise increment mutant ownership count. 00242 // If the result count is one, then remove the mutant object from the 00243 // thread's owned mutant list, set the owner thread to NULL, and attempt 00244 // to satisfy a Wait for the mutant object if the mutant object wait 00245 // list is not empty. 00246 // 00247 00248 Thread = KeGetCurrentThread(); 00249 if (Abandoned != FALSE) { 00250 Mutant->Header.SignalState = 1; 00251 Mutant->Abandoned = TRUE; 00252 00253 } else { 00254 00255 // 00256 // If the Mutant object is not owned by the current thread, then 00257 // unlock the dispatcher data base and raise an exception. Otherwise 00258 // increment the ownership count. 00259 // 00260 00261 if (Mutant->OwnerThread != Thread) { 00262 KiUnlockDispatcherDatabase(OldIrql); 00263 ExRaiseStatus(Mutant->Abandoned ? 00264 STATUS_ABANDONED : STATUS_MUTANT_NOT_OWNED); 00265 } 00266 00267 Mutant->Header.SignalState += 1; 00268 } 00269 00270 if (Mutant->Header.SignalState == 1) { 00271 if (OldState <= 0) { 00272 RemoveEntryList(&Mutant->MutantListEntry); 00273 Thread->KernelApcDisable += Mutant->ApcDisable; 00274 if ((Thread->KernelApcDisable == 0) && 00275 (IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]) == FALSE)) { 00276 Thread->ApcState.KernelApcPending = TRUE; 00277 KiRequestSoftwareInterrupt(APC_LEVEL); 00278 } 00279 } 00280 00281 Mutant->OwnerThread = (PKTHREAD)NULL; 00282 if (IsListEmpty(&Mutant->Header.WaitListHead) == FALSE) { 00283 KiWaitTest(Mutant, Increment); 00284 } 00285 } 00286 00287 // 00288 // If the value of the Wait argument is TRUE, then return to 00289 // caller with IRQL raised and the dispatcher database locked. 00290 // Else release the dispatcher database lock and lower IRQL to 00291 // its previous value. 00292 // 00293 00294 if (Wait != FALSE) { 00295 Thread->WaitNext = Wait; 00296 Thread->WaitIrql = OldIrql; 00297 00298 } else { 00299 KiUnlockDispatcherDatabase(OldIrql); 00300 } 00301 00302 // 00303 // Return previous signal state of mutant object. 00304 // 00305 00306 return OldState; 00307 } 00308 00309 LONG 00310 KeReleaseMutex ( 00311 IN PRKMUTANT Mutex, 00312 IN BOOLEAN Wait 00313 ) 00314 00315 /*++ 00316 00317 Routine Description: 00318 00319 This function releases a mutex object. 00320 00321 N.B. Kernel mutex objects have been subsumed by mutant objects. 00322 00323 Arguments: 00324 00325 Mutex - Supplies a pointer to a dispatcher object of type mutex. 00326 00327 Wait - Supplies a boolean value that signifies whether the call to 00328 KeReleaseMutex will be immediately followed by a call to one 00329 of the kernel Wait functions. 00330 00331 Return Value: 00332 00333 The previous signal state of the mutex object. 00334 00335 --*/ 00336 00337 { 00338 00339 ASSERT_MUTANT(Mutex); 00340 00341 // 00342 // Release the specified mutex object with defaults for increment 00343 // and abandoned parameters. 00344 // 00345 00346 return KeReleaseMutant(Mutex, 1, FALSE, Wait); 00347 } 00348 

Generated on Sat May 15 19:40:53 2004 for test by doxygen 1.3.7