- Simplified KeSetSystemAffinityThread and KeRevertToUserAffinityThread for non smp...
[reactos.git] / reactos / ntoskrnl / ke / sem.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/sem.c
23 * PURPOSE: Implements kernel semaphores
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * UPDATE HISTORY:
26 * Created 22/05/98
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ntoskrnl.h>
32 #define NDEBUG
33 #include <internal/debug.h>
34
35 /* FUNCTIONS *****************************************************************/
36
37 /*
38 * @implemented
39 */
40 VOID STDCALL
41 KeInitializeSemaphore (PKSEMAPHORE Semaphore,
42 LONG Count,
43 LONG Limit)
44 {
45 KeInitializeDispatcherHeader(&Semaphore->Header,
46 InternalSemaphoreType,
47 sizeof(KSEMAPHORE)/sizeof(ULONG),
48 Count);
49 Semaphore->Limit=Limit;
50 }
51
52 /*
53 * @implemented
54 */
55 LONG STDCALL
56 KeReadStateSemaphore (PKSEMAPHORE Semaphore)
57 {
58 return(Semaphore->Header.SignalState);
59 }
60
61 /*
62 * @implemented
63 */
64 LONG STDCALL
65 KeReleaseSemaphore (PKSEMAPHORE Semaphore,
66 KPRIORITY Increment,
67 LONG Adjustment,
68 BOOLEAN Wait)
69 /*
70 * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
71 * routine supplies a runtime priority boost for waiting threads. If this
72 * call sets the semaphore to the Signaled state, the semaphore count is
73 * augmented by the given value. The caller can also specify whether it
74 * will call one of the KeWaitXXX routines as soon as KeReleaseSemaphore
75 * returns control.
76 * ARGUMENTS:
77 * Semaphore = Points to an initialized semaphore object for which the
78 * caller provides the storage.
79 * Increment = Specifies the priority increment to be applied if
80 * releasing the semaphore causes a wait to be
81 * satisfied.
82 * Adjustment = Specifies a value to be added to the current semaphore
83 * count. This value must be positive
84 * Wait = Specifies whether the call to KeReleaseSemaphore is to be
85 * followed immediately by a call to one of the KeWaitXXX.
86 * RETURNS: If the return value is zero, the previous state of the semaphore
87 * object is Not-Signaled.
88 */
89 {
90 ULONG InitialState;
91 KIRQL OldIrql;
92
93 DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
94 "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
95
96 OldIrql = KeAcquireDispatcherDatabaseLock();
97
98 InitialState = Semaphore->Header.SignalState;
99 if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
100 InitialState > InitialState + Adjustment)
101 {
102 ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
103 }
104
105 Semaphore->Header.SignalState += Adjustment;
106 if (InitialState == 0)
107 {
108 KiDispatcherObjectWake(&Semaphore->Header);
109 }
110
111 if (Wait == FALSE)
112 {
113 KeReleaseDispatcherDatabaseLock(OldIrql);
114 }
115 else
116 {
117 KTHREAD *Thread = KeGetCurrentThread();
118 Thread->WaitNext = TRUE;
119 Thread->WaitIrql = OldIrql;
120 }
121
122 return(InitialState);
123 }
124
125 /* EOF */