Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeneventobj.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
1.7.6.1
|