preliminary comment out the self-modifying code for RtlPrefetchMemoryNonTemporal
[reactos.git] / reactos / ntoskrnl / ke / sem.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/sem.c
5 * PURPOSE: Implements kernel semaphores
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * David Welch (welch@mcmail.com)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 /*
19 * @implemented
20 */
21 VOID
22 STDCALL
23 KeInitializeSemaphore(PKSEMAPHORE Semaphore,
24 LONG Count,
25 LONG Limit)
26 {
27 DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
28
29 /* Simply Initialize the Header */
30 KeInitializeDispatcherHeader(&Semaphore->Header,
31 SemaphoreObject,
32 sizeof(KSEMAPHORE) / sizeof(ULONG),
33 Count);
34
35 /* Set the Limit */
36 Semaphore->Limit = Limit;
37 }
38
39 /*
40 * @implemented
41 */
42 LONG
43 STDCALL
44 KeReadStateSemaphore(PKSEMAPHORE Semaphore)
45 {
46 /* Just return the Signal State */
47 return Semaphore->Header.SignalState;
48 }
49
50 /*
51 * @implemented
52 *
53 * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
54 * routine supplies a runtime priority boost for waiting threads. If this
55 * call sets the semaphore to the Signaled state, the semaphore count is
56 * augmented by the given value. The caller can also specify whether it
57 * will call one of the KeWaitXXX routines as soon as KeReleaseSemaphore
58 * returns control.
59 * ARGUMENTS:
60 * Semaphore = Points to an initialized semaphore object for which the
61 * caller provides the storage.
62 * Increment = Specifies the priority increment to be applied if
63 * releasing the semaphore causes a wait to be
64 * satisfied.
65 * Adjustment = Specifies a value to be added to the current semaphore
66 * count. This value must be positive
67 * Wait = Specifies whether the call to KeReleaseSemaphore is to be
68 * followed immediately by a call to one of the KeWaitXXX.
69 * RETURNS: If the return value is zero, the previous state of the semaphore
70 * object is Not-Signaled.
71 */
72 LONG
73 STDCALL
74 KeReleaseSemaphore(PKSEMAPHORE Semaphore,
75 KPRIORITY Increment,
76 LONG Adjustment,
77 BOOLEAN Wait)
78 {
79 LONG InitialState, State;
80 KIRQL OldIrql;
81 PKTHREAD CurrentThread;
82
83 DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n",
84 Semaphore,
85 Increment,
86 Adjustment,
87 Wait);
88
89 /* Lock the Dispatcher Database */
90 OldIrql = KeAcquireDispatcherDatabaseLock();
91
92 /* Save the Old State and get new one */
93 InitialState = Semaphore->Header.SignalState;
94 State = InitialState + Adjustment;
95
96 /* Check if the Limit was exceeded */
97 if ((Semaphore->Limit < State) || (InitialState > State))
98 {
99 /* Raise an error if it was exceeded */
100 KeReleaseDispatcherDatabaseLock(OldIrql);
101 ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
102 }
103
104 /* Now set the new state */
105 Semaphore->Header.SignalState = State;
106
107 /* Check if we should wake it */
108 if (!(InitialState) && !(IsListEmpty(&Semaphore->Header.WaitListHead)))
109 {
110 /* Wake the Semaphore */
111 KiWaitTest(&Semaphore->Header, Increment);
112 }
113
114 /* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
115 if (Wait == FALSE)
116 {
117 /* Release the Lock */
118 KeReleaseDispatcherDatabaseLock(OldIrql);
119 }
120 else
121 {
122 /* Set a wait */
123 CurrentThread = KeGetCurrentThread();
124 CurrentThread->WaitNext = TRUE;
125 CurrentThread->WaitIrql = OldIrql;
126 }
127
128 /* Return the previous state */
129 return InitialState;
130 }
131
132 /* EOF */