update for HEAD-2003091401
[reactos.git] / 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 <ddk/ntddk.h>
32 #include <internal/ke.h>
33 #include <internal/id.h>
34
35 #define NDEBUG
36 #include <internal/debug.h>
37
38 /* FUNCTIONS *****************************************************************/
39
40 /*
41  * @implemented
42  */
43 VOID STDCALL 
44 KeInitializeSemaphore (PKSEMAPHORE      Semaphore,
45                        LONG             Count,
46                        LONG             Limit)
47 {
48    KeInitializeDispatcherHeader(&Semaphore->Header,
49                                 InternalSemaphoreType,
50                                 sizeof(KSEMAPHORE)/sizeof(ULONG),
51                                 Count);
52    Semaphore->Limit=Limit;
53 }
54
55 /*
56  * @implemented
57  */
58 LONG STDCALL 
59 KeReadStateSemaphore (PKSEMAPHORE       Semaphore)
60 {
61    return(Semaphore->Header.SignalState);
62 }
63
64 /*
65  * @implemented
66  */
67 LONG STDCALL 
68 KeReleaseSemaphore (PKSEMAPHORE Semaphore,
69                     KPRIORITY   Increment,
70                     LONG                Adjustment,
71                     BOOLEAN             Wait)
72 /*
73  * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
74  * routine supplies a runtime priority boost for waiting threads. If this
75  * call sets the semaphore to the Signaled state, the semaphore count is
76  * augmented by the given value. The caller can also specify whether it
77  * will call one of the KeWaitXXX routines as soon as KeReleaseSemaphore
78  * returns control.
79  * ARGUMENTS:
80  *       Semaphore = Points to an initialized semaphore object for which the
81  *                   caller provides the storage.
82  *       Increment = Specifies the priority increment to be applied if
83  *                   releasing the semaphore causes a wait to be 
84  *                   satisfied.
85  *       Adjustment = Specifies a value to be added to the current semaphore
86  *                    count. This value must be positive
87  *       Wait = Specifies whether the call to KeReleaseSemaphore is to be
88  *              followed immediately by a call to one of the KeWaitXXX.
89  * RETURNS: If the return value is zero, the previous state of the semaphore
90  *          object is Not-Signaled.
91  */
92 {
93    ULONG InitialState;
94   
95    DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
96           "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
97    
98    KeAcquireDispatcherDatabaseLock(Wait);
99    
100    InitialState = Semaphore->Header.SignalState;
101    if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
102        InitialState > InitialState + Adjustment)
103      {
104         ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
105      }
106    
107    Semaphore->Header.SignalState += Adjustment;
108    if (InitialState == 0)
109      {
110        KeDispatcherObjectWake(&Semaphore->Header);
111      }
112    
113   KeReleaseDispatcherDatabaseLock(Wait);
114   return(InitialState);
115 }
116
117 /* EOF */