ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

keyedevt.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.