Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkeyedevt.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel 00004 * FILE: ntoskrnl/ex/keyedevt.c 00005 * PURPOSE: Support for keyed events 00006 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* INTERNAL TYPES *************************************************************/ 00016 00017 #define NUM_KEY_HASH_BUCKETS 23 00018 typedef struct _EX_KEYED_EVENT 00019 { 00020 struct 00021 { 00022 EX_PUSH_LOCK Lock; 00023 LIST_ENTRY WaitListHead; 00024 LIST_ENTRY ReleaseListHead; 00025 } HashTable[NUM_KEY_HASH_BUCKETS]; 00026 } EX_KEYED_EVENT, *PEX_KEYED_EVENT; 00027 00028 VOID 00029 NTAPI 00030 ExpInitializeKeyedEvent( 00031 _Out_ PEX_KEYED_EVENT KeyedEvent); 00032 00033 #define KeGetCurrentProcess() ((PKPROCESS)PsGetCurrentProcess()) 00034 00035 /* GLOBALS *******************************************************************/ 00036 00037 PEX_KEYED_EVENT ExpCritSecOutOfMemoryEvent; 00038 POBJECT_TYPE ExKeyedEventObjectType; 00039 00040 static 00041 GENERIC_MAPPING ExpKeyedEventMapping = 00042 { 00043 STANDARD_RIGHTS_READ | EVENT_QUERY_STATE, 00044 STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE, 00045 STANDARD_RIGHTS_EXECUTE | EVENT_QUERY_STATE, 00046 EVENT_ALL_ACCESS 00047 }; 00048 00049 00050 /* FUNCTIONS *****************************************************************/ 00051 00052 VOID 00053 NTAPI 00054 ExpInitializeKeyedEventImplementation(VOID) 00055 { 00056 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer = {0}; 00057 UNICODE_STRING TypeName = RTL_CONSTANT_STRING(L"KeyedEvent"); 00058 NTSTATUS Status; 00059 00060 /* Set up the object type initializer */ 00061 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00062 ObjectTypeInitializer.GenericMapping = ExpKeyedEventMapping; 00063 ObjectTypeInitializer.PoolType = NonPagedPool; 00064 //ObjectTypeInitializer.DeleteProcedure = ???; 00065 //ObjectTypeInitializer.OkayToCloseProcedure = ???; 00066 00067 /* Create the keyed event object type */ 00068 Status = ObCreateObjectType(&TypeName, 00069 &ObjectTypeInitializer, 00070 NULL, 00071 &ExKeyedEventObjectType); 00072 00073 /* Check for success */ 00074 if (!NT_SUCCESS(Status)) 00075 { 00076 // FIXME 00077 KeBugCheck(0); 00078 } 00079 00080 /* Create the global keyed event for critical sections on low memory */ 00081 Status = ObCreateObject(KernelMode, 00082 ExKeyedEventObjectType, 00083 NULL, 00084 UserMode, 00085 NULL, 00086 sizeof(EX_KEYED_EVENT), 00087 0, 00088 0, 00089 (PVOID*)&ExpCritSecOutOfMemoryEvent); 00090 00091 /* Check for success */ 00092 if (!NT_SUCCESS(Status)) 00093 { 00094 // FIXME 00095 KeBugCheck(0); 00096 } 00097 00098 /* Initalize the keyed event */ 00099 ExpInitializeKeyedEvent(ExpCritSecOutOfMemoryEvent); 00100 } 00101 00102 VOID 00103 NTAPI 00104 ExpInitializeKeyedEvent( 00105 _Out_ PEX_KEYED_EVENT KeyedEvent) 00106 { 00107 ULONG i; 00108 00109 /* Loop all hash buckets */ 00110 for (i = 0; i < NUM_KEY_HASH_BUCKETS; i++) 00111 { 00112 /* Initialize the mutex and the wait lists */ 00113 ExInitializePushLock(&KeyedEvent->HashTable[i].Lock); 00114 InitializeListHead(&KeyedEvent->HashTable[i].WaitListHead); 00115 InitializeListHead(&KeyedEvent->HashTable[i].ReleaseListHead); 00116 } 00117 } 00118 00119 NTSTATUS 00120 NTAPI 00121 ExpReleaseOrWaitForKeyedEvent( 00122 _Inout_ PEX_KEYED_EVENT KeyedEvent, 00123 _In_ PVOID KeyedWaitValue, 00124 _In_ BOOLEAN Alertable, 00125 _In_ PLARGE_INTEGER Timeout, 00126 _In_ BOOLEAN Release) 00127 { 00128 PETHREAD Thread, CurrentThread; 00129 PKPROCESS CurrentProcess; 00130 PLIST_ENTRY ListEntry, WaitListHead1, WaitListHead2; 00131 NTSTATUS Status; 00132 ULONG_PTR HashIndex; 00133 00134 /* Get the current process */ 00135 CurrentProcess = KeGetCurrentProcess(); 00136 00137 /* Calculate the hash index */ 00138 HashIndex = (ULONG_PTR)KeyedWaitValue >> 5; 00139 HashIndex ^= (ULONG_PTR)CurrentProcess >> 6; 00140 HashIndex %= NUM_KEY_HASH_BUCKETS; 00141 00142 /* Lock the lists */ 00143 ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); 00144 00145 /* Get the lists for search and wait, depending on whether 00146 we want to wait for the event or signal it */ 00147 if (Release) 00148 { 00149 WaitListHead1 = &KeyedEvent->HashTable[HashIndex].WaitListHead; 00150 WaitListHead2 = &KeyedEvent->HashTable[HashIndex].ReleaseListHead; 00151 } 00152 else 00153 { 00154 WaitListHead1 = &KeyedEvent->HashTable[HashIndex].ReleaseListHead; 00155 WaitListHead2 = &KeyedEvent->HashTable[HashIndex].WaitListHead; 00156 } 00157 00158 /* loop the first wait list */ 00159 ListEntry = WaitListHead1->Flink; 00160 while (ListEntry != WaitListHead1) 00161 { 00162 Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain); 00163 00164 /* Check if this thread is a correct waiter */ 00165 if ((Thread->Tcb.Process == CurrentProcess) && 00166 (Thread->KeyedWaitValue == KeyedWaitValue)) 00167 { 00168 /* Remove the thread from the list */ 00169 RemoveEntryList(&Thread->KeyedWaitChain); 00170 00171 /* Wake the thread */ 00172 KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, 0, 1, FALSE); 00173 00174 /* Unlock the lists */ 00175 ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); 00176 00177 return STATUS_SUCCESS; 00178 } 00179 } 00180 00181 /* Get the current thread */ 00182 CurrentThread = PsGetCurrentThread(); 00183 00184 /* Set the wait key */ 00185 CurrentThread->KeyedWaitValue = KeyedWaitValue; 00186 00187 /* Initialize the wait semaphore */ 00188 KeInitializeSemaphore(&CurrentThread->KeyedWaitSemaphore, 0, 1); 00189 00190 /* Insert the current thread into the secondary wait list */ 00191 InsertTailList(WaitListHead2, &CurrentThread->KeyedWaitChain); 00192 00193 /* Unlock the lists */ 00194 ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); 00195 00196 /* Wait for the keyed wait semaphore */ 00197 Status = KeWaitForSingleObject(&CurrentThread->KeyedWaitSemaphore, 00198 WrKeyedEvent, 00199 KernelMode, 00200 Alertable, 00201 Timeout); 00202 00203 return STATUS_SUCCESS; 00204 } 00205 00206 NTSTATUS 00207 NTAPI 00208 ExpWaitForKeyedEvent( 00209 _Inout_ PEX_KEYED_EVENT KeyedEvent, 00210 _In_ PVOID KeyedWaitValue, 00211 _In_ BOOLEAN Alertable, 00212 _In_ PLARGE_INTEGER Timeout) 00213 { 00214 /* Call the generic internal function */ 00215 return ExpReleaseOrWaitForKeyedEvent(KeyedEvent, 00216 KeyedWaitValue, 00217 Alertable, 00218 Timeout, 00219 FALSE); 00220 } 00221 00222 NTSTATUS 00223 NTAPI 00224 ExpReleaseKeyedEvent( 00225 _Inout_ PEX_KEYED_EVENT KeyedEvent, 00226 _In_ PVOID KeyedWaitValue, 00227 _In_ BOOLEAN Alertable, 00228 _In_ PLARGE_INTEGER Timeout) 00229 { 00230 /* Call the generic internal function */ 00231 return ExpReleaseOrWaitForKeyedEvent(KeyedEvent, 00232 KeyedWaitValue, 00233 Alertable, 00234 Timeout, 00235 TRUE); 00236 } 00237 00238 NTSTATUS 00239 NTAPI 00240 NtCreateKeyedEvent( 00241 _Out_ PHANDLE OutHandle, 00242 _In_ ACCESS_MASK AccessMask, 00243 _In_ POBJECT_ATTRIBUTES ObjectAttributes, 00244 _In_ ULONG Flags) 00245 { 00246 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00247 PEX_KEYED_EVENT KeyedEvent; 00248 HANDLE KeyedEventHandle; 00249 NTSTATUS Status; 00250 00251 /* Check flags */ 00252 if (Flags != 0) 00253 { 00254 /* We don't support any flags yet */ 00255 return STATUS_INVALID_PARAMETER; 00256 } 00257 00258 /* Create the object */ 00259 Status = ObCreateObject(PreviousMode, 00260 ExKeyedEventObjectType, 00261 ObjectAttributes, 00262 PreviousMode, 00263 NULL, 00264 sizeof(EX_KEYED_EVENT), 00265 0, 00266 0, 00267 (PVOID*)&KeyedEvent); 00268 00269 /* Check for success */ 00270 if (!NT_SUCCESS(Status)) return Status; 00271 00272 /* Initalize the keyed event */ 00273 ExpInitializeKeyedEvent(KeyedEvent); 00274 00275 /* Insert it */ 00276 Status = ObInsertObject(KeyedEvent, 00277 NULL, 00278 AccessMask, 00279 0, 00280 NULL, 00281 &KeyedEventHandle); 00282 00283 /* Check for success (ObInsertObject dereferences!) */ 00284 if (!NT_SUCCESS(Status)) return Status; 00285 00286 if (PreviousMode != KernelMode) 00287 { 00288 /* Enter SEH for return */ 00289 _SEH2_TRY 00290 { 00291 /* Return the handle to the caller */ 00292 ProbeForWrite(OutHandle, sizeof(HANDLE), sizeof(HANDLE)); 00293 *OutHandle = KeyedEventHandle; 00294 } 00295 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00296 { 00297 /* Get the exception code */ 00298 Status = _SEH2_GetExceptionCode(); 00299 00300 /* Cleanup */ 00301 ObCloseHandle(KeyedEventHandle, PreviousMode); 00302 } 00303 _SEH2_END; 00304 } 00305 else 00306 { 00307 *OutHandle = KeyedEventHandle; 00308 } 00309 00310 /* Return Status */ 00311 return Status; 00312 } 00313 00314 NTSTATUS 00315 NTAPI 00316 NtOpenKeyedEvent( 00317 _Out_ PHANDLE OutHandle, 00318 _In_ ACCESS_MASK AccessMask, 00319 _In_ POBJECT_ATTRIBUTES ObjectAttributes) 00320 { 00321 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00322 HANDLE KeyedEventHandle; 00323 NTSTATUS Status; 00324 00325 /* Open the object */ 00326 Status = ObOpenObjectByName(ObjectAttributes, 00327 ExKeyedEventObjectType, 00328 PreviousMode, 00329 NULL, 00330 AccessMask, 00331 NULL, 00332 &KeyedEventHandle); 00333 00334 /* Check for success */ 00335 if (!NT_SUCCESS(Status)) return Status; 00336 00337 /* Enter SEH for return */ 00338 if (PreviousMode != KernelMode) 00339 { 00340 _SEH2_TRY 00341 { 00342 /* Return the handle to the caller */ 00343 ProbeForWrite(OutHandle, sizeof(HANDLE), sizeof(HANDLE)); 00344 *OutHandle = KeyedEventHandle; 00345 } 00346 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00347 { 00348 /* Get the exception code */ 00349 Status = _SEH2_GetExceptionCode(); 00350 } 00351 _SEH2_END; 00352 } 00353 else 00354 { 00355 *OutHandle = KeyedEventHandle; 00356 } 00357 00358 /* Return status */ 00359 return Status; 00360 } 00361 00362 NTSTATUS 00363 NTAPI 00364 NtWaitForKeyedEvent( 00365 _In_ HANDLE Handle, 00366 _In_ PVOID Key, 00367 _In_ BOOLEAN Alertable, 00368 _In_ PLARGE_INTEGER Timeout) 00369 { 00370 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00371 PEX_KEYED_EVENT KeyedEvent; 00372 NTSTATUS Status; 00373 00374 /* Check if the caller provided a handle */ 00375 if (Handle != NULL) 00376 { 00377 /* Get the keyed event object */ 00378 Status = ObReferenceObjectByHandle(Handle, 00379 EVENT_MODIFY_STATE, 00380 ExKeyedEventObjectType, 00381 PreviousMode, 00382 (PVOID*)&KeyedEvent, 00383 NULL); 00384 00385 /* Check for success */ 00386 if (!NT_SUCCESS(Status)) return Status; 00387 } 00388 else 00389 { 00390 /* Use the default keyed event for low memory critical sections */ 00391 KeyedEvent = ExpCritSecOutOfMemoryEvent; 00392 } 00393 00394 /* Do the wait */ 00395 Status = ExpWaitForKeyedEvent(KeyedEvent, Key, Alertable, Timeout); 00396 00397 /* Dereference the keyed event */ 00398 ObDereferenceObject(KeyedEvent); 00399 00400 /* Return the status */ 00401 return Status; 00402 } 00403 00404 NTSTATUS 00405 NTAPI 00406 NtReleaseKeyedEvent( 00407 _In_ HANDLE Handle, 00408 _In_ PVOID Key, 00409 _In_ BOOLEAN Alertable, 00410 _In_ PLARGE_INTEGER Timeout) 00411 { 00412 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00413 PEX_KEYED_EVENT KeyedEvent; 00414 NTSTATUS Status; 00415 00416 /* Check if the caller provided a handle */ 00417 if (Handle != NULL) 00418 { 00419 /* Get the keyed event object */ 00420 Status = ObReferenceObjectByHandle(Handle, 00421 EVENT_MODIFY_STATE, 00422 ExKeyedEventObjectType, 00423 PreviousMode, 00424 (PVOID*)&KeyedEvent, 00425 NULL); 00426 00427 /* Check for success */ 00428 if (!NT_SUCCESS(Status)) return Status; 00429 } 00430 else 00431 { 00432 /* Use the default keyed event for low memory critical sections */ 00433 KeyedEvent = ExpCritSecOutOfMemoryEvent; 00434 } 00435 00436 /* Do the wait */ 00437 Status = ExpReleaseKeyedEvent(KeyedEvent, Key, Alertable, Timeout); 00438 00439 /* Dereference the keyed event */ 00440 ObDereferenceObject(KeyedEvent); 00441 00442 /* Return the status */ 00443 return Status; 00444 } 00445 00446 /* EOF */ Generated on Sun May 27 2012 04:37:10 for ReactOS by
1.7.6.1
|