2005-03-14 06:44:31 +00:00
|
|
|
/*
|
2006-09-10 19:14:03 +00:00
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2015-10-04 11:54:25 +00:00
|
|
|
* FILE: ntoskrnl/ke/eventobj.c
|
2006-09-10 19:14:03 +00:00
|
|
|
* PURPOSE: Implements the Event Dispatcher Object
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
2006-09-10 19:14:03 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
1998-09-05 17:34:23 +00:00
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2006-09-10 19:14:03 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
|
|
|
KeClearEvent(IN PKEVENT Event)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2006-09-10 19:14:03 +00:00
|
|
|
ASSERT_EVENT(Event);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Reset Signal State */
|
|
|
|
Event->Header.SignalState = FALSE;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
2010-03-03 16:03:14 +00:00
|
|
|
KeInitializeEvent(OUT PKEVENT Event,
|
2006-09-10 19:14:03 +00:00
|
|
|
IN EVENT_TYPE Type,
|
|
|
|
IN BOOLEAN State)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Initialize the Dispatcher Header */
|
2011-10-07 16:18:52 +00:00
|
|
|
Event->Header.Type = Type;
|
|
|
|
//Event->Header.Signalling = FALSE; // fails in kmtest
|
|
|
|
Event->Header.Size = sizeof(KEVENT) / sizeof(ULONG);
|
|
|
|
Event->Header.SignalState = State;
|
|
|
|
InitializeListHead(&(Event->Header.WaitListHead));
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
|
|
|
KeInitializeEventPair(IN PKEVENT_PAIR EventPair)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Initialize the Event Pair Type and Size */
|
|
|
|
EventPair->Type = EventPairObject;
|
|
|
|
EventPair->Size = sizeof(KEVENT_PAIR);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Initialize the two Events */
|
|
|
|
KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
|
|
|
|
KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2006-09-10 19:14:03 +00:00
|
|
|
LONG
|
|
|
|
NTAPI
|
2005-03-14 02:08:17 +00:00
|
|
|
KePulseEvent(IN PKEVENT Event,
|
|
|
|
IN KPRIORITY Increment,
|
|
|
|
IN BOOLEAN Wait)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
LONG PreviousState;
|
2006-09-10 19:14:03 +00:00
|
|
|
PKTHREAD Thread;
|
|
|
|
ASSERT_EVENT(Event);
|
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Lock the Dispatcher Database */
|
2006-09-10 18:26:50 +00:00
|
|
|
OldIrql = KiAcquireDispatcherLock();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Save the Old State */
|
|
|
|
PreviousState = Event->Header.SignalState;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Check if we are non-signaled and we have stuff in the Wait Queue */
|
2006-09-10 19:14:03 +00:00
|
|
|
if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead))
|
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Set the Event to Signaled */
|
|
|
|
Event->Header.SignalState = 1;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Wake the Event */
|
Dispatching & Queue Rewrite II:
- Rewrote wait code. It is now cleaner, more optimized and faster. All waiting
functions are now clearly differentiated instead of sharing code. These functions
are called up to a dozen times a second, so having dedicated code for each of
them is a real boost in speed.
- Fixed several queue issues, made a dedicated queue wait/wake function (you are not
supposed to use KeWaitFor on a queue, and this is also a speed boost), and make it
compatible with new wait code.
- Optimized Work Queue code to be much smaller and better organized, by using an
array instead of hard-coded multiple static variables. Also, add support for the
real NT structures and implementation, paving the road for Dynamic Work Items, which
also have timeouts, and deadlock dection + debug info.
- Simplified PsBlockThread and made it compatible with wait code.
- Added support for priority boosting when unwaiting a thread; will use later, as well
as put proper boosting for dispatch objects.
- Inlined all dispatcher lock functions and header initialization for speed.
- Moved executive wait code into ob.
svn path=/trunk/; revision=14047
2005-03-14 05:54:32 +00:00
|
|
|
KiWaitTest(&Event->Header, Increment);
|
2005-03-14 02:08:17 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Unsignal it */
|
|
|
|
Event->Header.SignalState = 0;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Check what wait state was requested */
|
2006-09-10 19:14:03 +00:00
|
|
|
if (Wait == FALSE)
|
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
/* Wait not requested, release Dispatcher Database and return */
|
2006-09-10 18:26:50 +00:00
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
2006-09-10 19:14:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Return Locked and with a Wait */
|
2006-09-10 19:14:03 +00:00
|
|
|
Thread = KeGetCurrentThread();
|
2005-03-14 02:08:17 +00:00
|
|
|
Thread->WaitNext = TRUE;
|
|
|
|
Thread->WaitIrql = OldIrql;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the previous State */
|
|
|
|
return PreviousState;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
LONG
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
|
|
|
KeReadStateEvent(IN PKEVENT Event)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2006-09-10 19:14:03 +00:00
|
|
|
ASSERT_EVENT(Event);
|
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Return the Signal State */
|
|
|
|
return Event->Header.SignalState;
|
|
|
|
}
|
2005-02-28 17:40:15 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
LONG
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
|
|
|
KeResetEvent(IN PKEVENT Event)
|
2005-03-14 02:08:17 +00:00
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
|
|
LONG PreviousState;
|
2006-09-10 19:14:03 +00:00
|
|
|
ASSERT_EVENT(Event);
|
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Lock the Dispatcher Database */
|
2006-09-10 18:26:50 +00:00
|
|
|
OldIrql = KiAcquireDispatcherLock();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Save the Previous State */
|
|
|
|
PreviousState = Event->Header.SignalState;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Set it to zero */
|
|
|
|
Event->Header.SignalState = 0;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
|
|
/* Release Dispatcher Database and return previous state */
|
2006-09-10 18:26:50 +00:00
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
2005-03-14 02:08:17 +00:00
|
|
|
return PreviousState;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
2000-07-04 01:30:18 +00:00
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-03-14 02:08:17 +00:00
|
|
|
LONG
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
|
|
|
KeSetEvent(IN PKEVENT Event,
|
|
|
|
IN KPRIORITY Increment,
|
|
|
|
IN BOOLEAN Wait)
|
2000-07-04 01:30:18 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
LONG PreviousState;
|
2006-09-10 19:14:03 +00:00
|
|
|
PKTHREAD Thread;
|
|
|
|
ASSERT_EVENT(Event);
|
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-03-14 02:08:17 +00:00
|
|
|
|
2006-09-14 03:49:20 +00:00
|
|
|
/*
|
|
|
|
* Check if this is an signaled notification event without an upcoming wait.
|
|
|
|
* In this case, we can immediately return TRUE, without locking.
|
|
|
|
*/
|
[NTOS]: Remove useless variables in kernel code that were set, but never actually used (dead code, tests, copy/pasters). If a variable was set but not used because of missing/#if'ed out code, a note was added instead.
[NTOS]: In the process, fix bugs in the Event dispatcher code that used Win32 EVENT_TYPE instead of NT KOBJECTS enumeration.
[NTOS]: Fix a bug in ObpInsertHandleCount, where the object access check was being done with the previous mode, instead of honoring the probe mode, which is defined by OBJ_FORCE_ACCESS_CHECK.
[NTOS]: Fix a bug in a section function which was always returning STATUS_SUCCESS, now it returns the result of the previous Status = function assignment. If this isn't desired, then don't check for the Status anymore.
[NTOS]: Note that MDL code does not support SkipBytes argument. If it is used, MDL could be invalid.
[NTOS]: Add checks for VerifierAllocation and set it when needed (WIP).
[NTOS]: Clarify what _WORKING_LINKER_ is, and the legal risks in continuing to use a linker that builds non-Microsoft drivers when used with headers whose EULA specify that they can only be used for Microsoft drivers.
svn path=/trunk/; revision=48692
2010-09-04 08:17:17 +00:00
|
|
|
if ((Event->Header.Type == EventNotificationObject) &&
|
2006-09-14 03:49:20 +00:00
|
|
|
(Event->Header.SignalState == 1) &&
|
|
|
|
!(Wait))
|
|
|
|
{
|
|
|
|
/* Return the signal state (TRUE/Signalled) */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Lock the Dispathcer Database */
|
2006-09-10 18:26:50 +00:00
|
|
|
OldIrql = KiAcquireDispatcherLock();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Save the Previous State */
|
|
|
|
PreviousState = Event->Header.SignalState;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Set the Event to Signaled */
|
|
|
|
Event->Header.SignalState = 1;
|
|
|
|
|
|
|
|
/* Check if the event just became signaled now, and it has waiters */
|
|
|
|
if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))
|
2006-09-10 19:14:03 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Check the type of event */
|
[NTOS]: Remove useless variables in kernel code that were set, but never actually used (dead code, tests, copy/pasters). If a variable was set but not used because of missing/#if'ed out code, a note was added instead.
[NTOS]: In the process, fix bugs in the Event dispatcher code that used Win32 EVENT_TYPE instead of NT KOBJECTS enumeration.
[NTOS]: Fix a bug in ObpInsertHandleCount, where the object access check was being done with the previous mode, instead of honoring the probe mode, which is defined by OBJ_FORCE_ACCESS_CHECK.
[NTOS]: Fix a bug in a section function which was always returning STATUS_SUCCESS, now it returns the result of the previous Status = function assignment. If this isn't desired, then don't check for the Status anymore.
[NTOS]: Note that MDL code does not support SkipBytes argument. If it is used, MDL could be invalid.
[NTOS]: Add checks for VerifierAllocation and set it when needed (WIP).
[NTOS]: Clarify what _WORKING_LINKER_ is, and the legal risks in continuing to use a linker that builds non-Microsoft drivers when used with headers whose EULA specify that they can only be used for Microsoft drivers.
svn path=/trunk/; revision=48692
2010-09-04 08:17:17 +00:00
|
|
|
if (Event->Header.Type == EventNotificationObject)
|
2006-09-10 19:14:03 +00:00
|
|
|
{
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Unwait the thread */
|
|
|
|
KxUnwaitThread(&Event->Header, Increment);
|
2006-09-10 19:14:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Otherwise unwait the thread and unsignal the event */
|
|
|
|
KxUnwaitThreadForEvent(Event, Increment);
|
2005-03-14 02:08:17 +00:00
|
|
|
}
|
2003-11-02 01:16:21 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Check what wait state was requested */
|
2006-09-10 19:14:03 +00:00
|
|
|
if (!Wait)
|
|
|
|
{
|
2005-05-09 01:38:29 +00:00
|
|
|
/* Wait not requested, release Dispatcher Database and return */
|
2006-09-10 18:26:50 +00:00
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
2006-09-10 19:14:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Return Locked and with a Wait */
|
2006-09-10 19:14:03 +00:00
|
|
|
Thread = KeGetCurrentThread();
|
2005-03-14 02:08:17 +00:00
|
|
|
Thread->WaitNext = TRUE;
|
|
|
|
Thread->WaitIrql = OldIrql;
|
2003-11-02 01:16:21 +00:00
|
|
|
}
|
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Return the previous State */
|
|
|
|
return PreviousState;
|
2000-07-04 01:30:18 +00:00
|
|
|
}
|
|
|
|
|
2004-06-23 22:32:24 +00:00
|
|
|
/*
|
2004-10-13 22:27:03 +00:00
|
|
|
* @implemented
|
2004-06-23 22:32:24 +00:00
|
|
|
*/
|
|
|
|
VOID
|
2006-09-10 19:14:03 +00:00
|
|
|
NTAPI
|
2005-03-14 02:08:17 +00:00
|
|
|
KeSetEventBoostPriority(IN PKEVENT Event,
|
2006-09-14 03:49:20 +00:00
|
|
|
IN PKTHREAD *WaitingThread OPTIONAL)
|
2004-06-23 22:32:24 +00:00
|
|
|
{
|
2005-03-14 02:08:17 +00:00
|
|
|
KIRQL OldIrql;
|
2006-09-14 03:49:20 +00:00
|
|
|
PKWAIT_BLOCK WaitBlock;
|
|
|
|
PKTHREAD Thread = KeGetCurrentThread(), WaitThread;
|
[NTOS]: Remove useless variables in kernel code that were set, but never actually used (dead code, tests, copy/pasters). If a variable was set but not used because of missing/#if'ed out code, a note was added instead.
[NTOS]: In the process, fix bugs in the Event dispatcher code that used Win32 EVENT_TYPE instead of NT KOBJECTS enumeration.
[NTOS]: Fix a bug in ObpInsertHandleCount, where the object access check was being done with the previous mode, instead of honoring the probe mode, which is defined by OBJ_FORCE_ACCESS_CHECK.
[NTOS]: Fix a bug in a section function which was always returning STATUS_SUCCESS, now it returns the result of the previous Status = function assignment. If this isn't desired, then don't check for the Status anymore.
[NTOS]: Note that MDL code does not support SkipBytes argument. If it is used, MDL could be invalid.
[NTOS]: Add checks for VerifierAllocation and set it when needed (WIP).
[NTOS]: Clarify what _WORKING_LINKER_ is, and the legal risks in continuing to use a linker that builds non-Microsoft drivers when used with headers whose EULA specify that they can only be used for Microsoft drivers.
svn path=/trunk/; revision=48692
2010-09-04 08:17:17 +00:00
|
|
|
ASSERT(Event->Header.Type == EventSynchronizationObject);
|
2006-09-10 19:14:03 +00:00
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-03-14 02:08:17 +00:00
|
|
|
|
|
|
|
/* Acquire Dispatcher Database Lock */
|
2006-09-10 18:26:50 +00:00
|
|
|
OldIrql = KiAcquireDispatcherLock();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Check if the list is empty */
|
2006-09-10 19:14:03 +00:00
|
|
|
if (IsListEmpty(&Event->Header.WaitListHead))
|
|
|
|
{
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Set the Event to Signaled */
|
|
|
|
Event->Header.SignalState = 1;
|
|
|
|
|
|
|
|
/* Return */
|
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the Wait Block */
|
|
|
|
WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
|
|
|
|
KWAIT_BLOCK,
|
|
|
|
WaitListEntry);
|
|
|
|
|
|
|
|
/* Check if this is a WaitAll */
|
|
|
|
if (WaitBlock->WaitType == WaitAll)
|
|
|
|
{
|
|
|
|
/* Set the Event to Signaled */
|
2005-03-14 02:08:17 +00:00
|
|
|
Event->Header.SignalState = 1;
|
2006-09-14 03:49:20 +00:00
|
|
|
|
|
|
|
/* Unwait the thread and unsignal the event */
|
|
|
|
KxUnwaitThreadForEvent(Event, EVENT_INCREMENT);
|
2006-09-10 19:14:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Return waiting thread to caller */
|
|
|
|
WaitThread = WaitBlock->Thread;
|
|
|
|
if (WaitingThread) *WaitingThread = WaitThread;
|
|
|
|
|
|
|
|
/* Calculate new priority */
|
2007-01-16 20:49:40 +00:00
|
|
|
Thread->Priority = KiComputeNewPriority(Thread, 0);
|
2006-09-14 03:49:20 +00:00
|
|
|
|
|
|
|
/* Unlink the waiting thread */
|
2007-01-16 20:49:40 +00:00
|
|
|
KiUnlinkThread(WaitThread, STATUS_SUCCESS);
|
2005-03-14 02:08:17 +00:00
|
|
|
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Request priority boosting */
|
|
|
|
WaitThread->AdjustIncrement = Thread->Priority;
|
2007-01-16 20:49:40 +00:00
|
|
|
WaitThread->AdjustReason = AdjustBoost;
|
2005-03-14 02:08:17 +00:00
|
|
|
|
2006-09-14 03:49:20 +00:00
|
|
|
/* Ready the thread */
|
|
|
|
KiReadyThread(WaitThread);
|
2005-03-14 02:08:17 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 02:08:17 +00:00
|
|
|
/* Release the Dispatcher Database Lock */
|
2006-09-10 18:26:50 +00:00
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
2004-06-23 22:32:24 +00:00
|
|
|
}
|
|
|
|
|
2000-07-04 01:30:18 +00:00
|
|
|
/* EOF */
|