2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/sem.c
5 * PURPOSE: Implements the Semaphore Dispatcher Object
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
22 KeInitializeSemaphore(IN PKSEMAPHORE Semaphore
,
26 /* Simply Initialize the Header */
27 Semaphore
->Header
.Type
= SemaphoreObject
;
28 Semaphore
->Header
.Size
= sizeof(KSEMAPHORE
) / sizeof(ULONG
);
29 Semaphore
->Header
.SignalState
= Count
;
30 InitializeListHead(&(Semaphore
->Header
.WaitListHead
));
33 Semaphore
->Limit
= Limit
;
41 KeReadStateSemaphore(IN PKSEMAPHORE Semaphore
)
43 ASSERT_SEMAPHORE(Semaphore
);
45 /* Just return the Signal State */
46 return Semaphore
->Header
.SignalState
;
54 KeReleaseSemaphore(IN PKSEMAPHORE Semaphore
,
55 IN KPRIORITY Increment
,
59 LONG InitialState
, State
;
61 PKTHREAD CurrentThread
;
62 ASSERT_SEMAPHORE(Semaphore
);
63 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
65 /* Lock the Dispatcher Database */
66 OldIrql
= KiAcquireDispatcherLock();
68 /* Save the Old State and get new one */
69 InitialState
= Semaphore
->Header
.SignalState
;
70 State
= InitialState
+ Adjustment
;
72 /* Check if the Limit was exceeded */
73 if ((Semaphore
->Limit
< State
) || (InitialState
> State
))
75 /* Raise an error if it was exceeded */
76 KiReleaseDispatcherLock(OldIrql
);
77 ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED
);
80 /* Now set the new state */
81 Semaphore
->Header
.SignalState
= State
;
83 /* Check if we should wake it */
84 if (!(InitialState
) && !(IsListEmpty(&Semaphore
->Header
.WaitListHead
)))
86 /* Wake the Semaphore */
87 KiWaitTest(&Semaphore
->Header
, Increment
);
90 /* Check if the caller wants to wait after this release */
93 /* Release the Lock */
94 KiReleaseDispatcherLock(OldIrql
);
99 CurrentThread
= KeGetCurrentThread();
100 CurrentThread
->WaitNext
= TRUE
;
101 CurrentThread
->WaitIrql
= OldIrql
;
104 /* Return the previous state */