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

eventobj.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/event.c
00005  * PURPOSE:         Implements the Event 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 KeClearEvent(IN PKEVENT Event)
00023 {
00024     ASSERT_EVENT(Event);
00025 
00026     /* Reset Signal State */
00027     Event->Header.SignalState = FALSE;
00028 }
00029 
00030 /*
00031  * @implemented
00032  */
00033 VOID
00034 NTAPI
00035 KeInitializeEvent(OUT PKEVENT Event,
00036                   IN EVENT_TYPE Type,
00037                   IN BOOLEAN State)
00038 {
00039     /* Initialize the Dispatcher Header */
00040     Event->Header.Type = Type;
00041     //Event->Header.Signalling = FALSE; // fails in kmtest
00042     Event->Header.Size = sizeof(KEVENT) / sizeof(ULONG);
00043     Event->Header.SignalState = State;
00044     InitializeListHead(&(Event->Header.WaitListHead));
00045 }
00046 
00047 /*
00048  * @implemented
00049  */
00050 VOID
00051 NTAPI
00052 KeInitializeEventPair(IN PKEVENT_PAIR EventPair)
00053 {
00054     /* Initialize the Event Pair Type and Size */
00055     EventPair->Type = EventPairObject;
00056     EventPair->Size = sizeof(KEVENT_PAIR);
00057 
00058     /* Initialize the two Events */
00059     KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
00060     KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
00061 }
00062 
00063 /*
00064  * @implemented
00065  */
00066 LONG
00067 NTAPI
00068 KePulseEvent(IN PKEVENT Event,
00069              IN KPRIORITY Increment,
00070              IN BOOLEAN Wait)
00071 {
00072     KIRQL OldIrql;
00073     LONG PreviousState;
00074     PKTHREAD Thread;
00075     ASSERT_EVENT(Event);
00076     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00077 
00078     /* Lock the Dispatcher Database */
00079     OldIrql = KiAcquireDispatcherLock();
00080 
00081     /* Save the Old State */
00082     PreviousState = Event->Header.SignalState;
00083 
00084     /* Check if we are non-signaled and we have stuff in the Wait Queue */
00085     if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead))
00086     {
00087         /* Set the Event to Signaled */
00088         Event->Header.SignalState = 1;
00089 
00090         /* Wake the Event */
00091         KiWaitTest(&Event->Header, Increment);
00092     }
00093 
00094     /* Unsignal it */
00095     Event->Header.SignalState = 0;
00096 
00097     /* Check what wait state was requested */
00098     if (Wait == FALSE)
00099     {
00100         /* Wait not requested, release Dispatcher Database and return */
00101         KiReleaseDispatcherLock(OldIrql);
00102     }
00103     else
00104     {
00105         /* Return Locked and with a Wait */
00106         Thread = KeGetCurrentThread();
00107         Thread->WaitNext = TRUE;
00108         Thread->WaitIrql = OldIrql;
00109     }
00110 
00111     /* Return the previous State */
00112     return PreviousState;
00113 }
00114 
00115 /*
00116  * @implemented
00117  */
00118 LONG
00119 NTAPI
00120 KeReadStateEvent(IN PKEVENT Event)
00121 {
00122     ASSERT_EVENT(Event);
00123 
00124     /* Return the Signal State */
00125     return Event->Header.SignalState;
00126 }
00127 
00128 /*
00129  * @implemented
00130  */
00131 LONG
00132 NTAPI
00133 KeResetEvent(IN PKEVENT Event)
00134 {
00135     KIRQL OldIrql;
00136     LONG PreviousState;
00137     ASSERT_EVENT(Event);
00138     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00139 
00140     /* Lock the Dispatcher Database */
00141     OldIrql = KiAcquireDispatcherLock();
00142 
00143     /* Save the Previous State */
00144     PreviousState = Event->Header.SignalState;
00145 
00146     /* Set it to zero */
00147     Event->Header.SignalState = 0;
00148 
00149     /* Release Dispatcher Database and return previous state */
00150     KiReleaseDispatcherLock(OldIrql);
00151     return PreviousState;
00152 }
00153 
00154 /*
00155  * @implemented
00156  */
00157 LONG
00158 NTAPI
00159 KeSetEvent(IN PKEVENT Event,
00160            IN KPRIORITY Increment,
00161            IN BOOLEAN Wait)
00162 {
00163     KIRQL OldIrql;
00164     LONG PreviousState;
00165     PKTHREAD Thread;
00166     ASSERT_EVENT(Event);
00167     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00168 
00169     /*
00170      * Check if this is an signaled notification event without an upcoming wait.
00171      * In this case, we can immediately return TRUE, without locking.
00172      */
00173     if ((Event->Header.Type == EventNotificationObject) &&
00174         (Event->Header.SignalState == 1) &&
00175         !(Wait))
00176     {
00177         /* Return the signal state (TRUE/Signalled) */
00178         return TRUE;
00179     }
00180 
00181     /* Lock the Dispathcer Database */
00182     OldIrql = KiAcquireDispatcherLock();
00183 
00184     /* Save the Previous State */
00185     PreviousState = Event->Header.SignalState;
00186 
00187     /* Set the Event to Signaled */
00188     Event->Header.SignalState = 1;
00189 
00190     /* Check if the event just became signaled now, and it has waiters */
00191     if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))
00192     {
00193         /* Check the type of event */
00194         if (Event->Header.Type == EventNotificationObject)
00195         {
00196             /* Unwait the thread */
00197             KxUnwaitThread(&Event->Header, Increment);
00198         }
00199         else
00200         {
00201             /* Otherwise unwait the thread and unsignal the event */
00202             KxUnwaitThreadForEvent(Event, Increment);
00203         }
00204     }
00205 
00206     /* Check what wait state was requested */
00207     if (!Wait)
00208     {
00209         /* Wait not requested, release Dispatcher Database and return */
00210         KiReleaseDispatcherLock(OldIrql);
00211     }
00212     else
00213     {
00214         /* Return Locked and with a Wait */
00215         Thread = KeGetCurrentThread();
00216         Thread->WaitNext = TRUE;
00217         Thread->WaitIrql = OldIrql;
00218     }
00219 
00220     /* Return the previous State */
00221     return PreviousState;
00222 }
00223 
00224 /*
00225  * @implemented
00226  */
00227 VOID
00228 NTAPI
00229 KeSetEventBoostPriority(IN PKEVENT Event,
00230                         IN PKTHREAD *WaitingThread OPTIONAL)
00231 {
00232     KIRQL OldIrql;
00233     PKWAIT_BLOCK WaitBlock;
00234     PKTHREAD Thread = KeGetCurrentThread(), WaitThread;
00235     ASSERT(Event->Header.Type == EventSynchronizationObject);
00236     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00237 
00238     /* Acquire Dispatcher Database Lock */
00239     OldIrql = KiAcquireDispatcherLock();
00240 
00241     /* Check if the list is empty */
00242     if (IsListEmpty(&Event->Header.WaitListHead))
00243     {
00244         /* Set the Event to Signaled */
00245         Event->Header.SignalState = 1;
00246 
00247         /* Return */
00248         KiReleaseDispatcherLock(OldIrql);
00249         return;
00250     }
00251 
00252     /* Get the Wait Block */
00253     WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
00254                                   KWAIT_BLOCK,
00255                                   WaitListEntry);
00256 
00257     /* Check if this is a WaitAll */
00258     if (WaitBlock->WaitType == WaitAll)
00259     {
00260         /* Set the Event to Signaled */
00261         Event->Header.SignalState = 1;
00262 
00263         /* Unwait the thread and unsignal the event */
00264         KxUnwaitThreadForEvent(Event, EVENT_INCREMENT);
00265     }
00266     else
00267     {
00268         /* Return waiting thread to caller */
00269         WaitThread = WaitBlock->Thread;
00270         if (WaitingThread) *WaitingThread = WaitThread;
00271 
00272         /* Calculate new priority */
00273         Thread->Priority = KiComputeNewPriority(Thread, 0);
00274 
00275         /* Unlink the waiting thread */
00276         KiUnlinkThread(WaitThread, STATUS_SUCCESS);
00277 
00278         /* Request priority boosting */
00279         WaitThread->AdjustIncrement = Thread->Priority;
00280         WaitThread->AdjustReason = AdjustBoost;
00281 
00282         /* Ready the thread */
00283         KiReadyThread(WaitThread);
00284     }
00285 
00286     /* Release the Dispatcher Database Lock */
00287     KiReleaseDispatcherLock(OldIrql);
00288 }
00289 
00290 /* EOF */

Generated on Sat May 26 2012 04:36:19 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.