Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ke/semphobj.c * PURPOSE: Implements the Semaphore Dispatcher Object * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* * @implemented */VOIDNTAPIKeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit){ /* Simply Initialize the Header */ Semaphore->Header.Type = SemaphoreObject; Semaphore->Header.Size = sizeof(KSEMAPHORE) / sizeof(ULONG); Semaphore->Header.SignalState = Count; InitializeListHead(&(Semaphore->Header.WaitListHead));
/* Set the Limit */ Semaphore->Limit = Limit;}
/* * @implemented */LONGNTAPIKeReadStateSemaphore(IN PKSEMAPHORE Semaphore){ ASSERT_SEMAPHORE(Semaphore);
/* Just return the Signal State */ return Semaphore->Header.SignalState;}
/* * @implemented */LONGNTAPIKeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait){ LONG InitialState, State; KIRQL OldIrql; PKTHREAD CurrentThread; ASSERT_SEMAPHORE(Semaphore); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */ OldIrql = KiAcquireDispatcherLock();
/* Save the Old State and get new one */ InitialState = Semaphore->Header.SignalState; State = InitialState + Adjustment;
/* Check if the Limit was exceeded */ if ((Semaphore->Limit < State) || (InitialState > State)) { /* Raise an error if it was exceeded */ KiReleaseDispatcherLock(OldIrql); ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); }
/* Now set the new state */ Semaphore->Header.SignalState = State;
/* Check if we should wake it */ if (!(InitialState) && !(IsListEmpty(&Semaphore->Header.WaitListHead))) { /* Wake the Semaphore */ KiWaitTest(&Semaphore->Header, Increment); }
/* Check if the caller wants to wait after this release */ if (Wait == FALSE) { /* Release the Lock */ KiReleaseDispatcherLock(OldIrql); } else { /* Set a wait */ CurrentThread = KeGetCurrentThread(); CurrentThread->WaitNext = TRUE; CurrentThread->WaitIrql = OldIrql; }
/* Return the previous state */ return InitialState;}
/* EOF */