Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ke/eventobj.c * PURPOSE: Implements the Event Dispatcher Object * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* * @implemented */VOIDNTAPIKeClearEvent(IN PKEVENT Event){ ASSERT_EVENT(Event);
/* Reset Signal State */ Event->Header.SignalState = FALSE;}
/* * @implemented */VOIDNTAPIKeInitializeEvent(OUT PKEVENT Event, IN EVENT_TYPE Type, IN BOOLEAN State){ /* Initialize the Dispatcher Header */ ASSERT((Type == NotificationEvent) || (Type == SynchronizationEvent)); Event->Header.Type = EventNotificationObject + Type; //Event->Header.Signalling = FALSE; // fails in kmtest Event->Header.Size = sizeof(KEVENT) / sizeof(ULONG); Event->Header.SignalState = State; InitializeListHead(&(Event->Header.WaitListHead));}
/* * @implemented */VOIDNTAPIKeInitializeEventPair(IN PKEVENT_PAIR EventPair){ /* Initialize the Event Pair Type and Size */ EventPair->Type = EventPairObject; EventPair->Size = sizeof(KEVENT_PAIR);
/* Initialize the two Events */ KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);}
/* * @implemented */LONGNTAPIKePulseEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait){ KIRQL OldIrql; LONG PreviousState; PKTHREAD Thread; ASSERT_EVENT(Event); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */ OldIrql = KiAcquireDispatcherLock();
/* Save the Old State */ PreviousState = Event->Header.SignalState;
/* Check if we are non-signaled and we have stuff in the Wait Queue */ if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead)) { /* Set the Event to Signaled */ Event->Header.SignalState = 1;
/* Wake the Event */ KiWaitTest(&Event->Header, Increment); }
/* Unsignal it */ Event->Header.SignalState = 0;
/* Check what wait state was requested */ if (Wait == FALSE) { /* Wait not requested, release Dispatcher Database and return */ KiReleaseDispatcherLock(OldIrql); } else { /* Return Locked and with a Wait */ Thread = KeGetCurrentThread(); Thread->WaitNext = TRUE; Thread->WaitIrql = OldIrql; }
/* Return the previous State */ return PreviousState;}
/* * @implemented */LONGNTAPIKeReadStateEvent(IN PKEVENT Event){ ASSERT_EVENT(Event);
/* Return the Signal State */ return Event->Header.SignalState;}
/* * @implemented */LONGNTAPIKeResetEvent(IN PKEVENT Event){ KIRQL OldIrql; LONG PreviousState; ASSERT_EVENT(Event); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */ OldIrql = KiAcquireDispatcherLock();
/* Save the Previous State */ PreviousState = Event->Header.SignalState;
/* Set it to zero */ Event->Header.SignalState = 0;
/* Release Dispatcher Database and return previous state */ KiReleaseDispatcherLock(OldIrql); return PreviousState;}
/* * @implemented */LONGNTAPIKeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait){ KIRQL OldIrql; LONG PreviousState; PKTHREAD Thread; ASSERT_EVENT(Event); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* * Check if this is an signaled notification event without an upcoming wait. * In this case, we can immediately return TRUE, without locking. */ if ((Event->Header.Type == EventNotificationObject) && (Event->Header.SignalState == 1) && !(Wait)) { /* Return the signal state (TRUE/Signalled) */ return TRUE; }
/* Lock the Dispathcer Database */ OldIrql = KiAcquireDispatcherLock();
/* Save the Previous State */ PreviousState = Event->Header.SignalState;
/* 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))) { /* Check the type of event */ if (Event->Header.Type == EventNotificationObject) { /* Unwait the thread */ KxUnwaitThread(&Event->Header, Increment); } else { /* Otherwise unwait the thread and unsignal the event */ KxUnwaitThreadForEvent(Event, Increment); } }
/* Check what wait state was requested */ if (!Wait) { /* Wait not requested, release Dispatcher Database and return */ KiReleaseDispatcherLock(OldIrql); } else { /* Return Locked and with a Wait */ Thread = KeGetCurrentThread(); Thread->WaitNext = TRUE; Thread->WaitIrql = OldIrql; }
/* Return the previous State */ return PreviousState;}
/* * @implemented */VOIDNTAPIKeSetEventBoostPriority(IN PKEVENT Event, IN PKTHREAD *WaitingThread OPTIONAL){ KIRQL OldIrql; PKWAIT_BLOCK WaitBlock; PKTHREAD Thread = KeGetCurrentThread(), WaitThread; ASSERT(Event->Header.Type == EventSynchronizationObject); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Acquire Dispatcher Database Lock */ OldIrql = KiAcquireDispatcherLock();
/* Check if the list is empty */ if (IsListEmpty(&Event->Header.WaitListHead)) { /* 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 */ Event->Header.SignalState = 1;
/* Unwait the thread and unsignal the event */ KxUnwaitThreadForEvent(Event, EVENT_INCREMENT); } else { /* Return waiting thread to caller */ WaitThread = WaitBlock->Thread; if (WaitingThread) *WaitingThread = WaitThread;
/* Calculate new priority */ Thread->Priority = KiComputeNewPriority(Thread, 0);
/* Unlink the waiting thread */ KiUnlinkThread(WaitThread, STATUS_SUCCESS);
/* Request priority boosting */ WaitThread->AdjustIncrement = Thread->Priority; WaitThread->AdjustReason = AdjustBoost;
/* Ready the thread */ KiReadyThread(WaitThread); }
/* Release the Dispatcher Database Lock */ KiReleaseDispatcherLock(OldIrql);}
/* EOF */