Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

semphobj.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 semphobj.c 00008 00009 Abstract: 00010 00011 This module implements the kernel semaphore object. Functions 00012 are provided to initialize, read, and release semaphore objects. 00013 00014 Author: 00015 00016 David N. Cutler (davec) 28-Feb-1989 00017 00018 Environment: 00019 00020 Kernel mode only. 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include "ki.h" 00027 00028 // 00029 // The following assert macro is used to check that an input semaphore is 00030 // really a ksemaphore and not something else, like deallocated pool. 00031 // 00032 00033 #define ASSERT_SEMAPHORE(E) { \ 00034 ASSERT((E)->Header.Type == SemaphoreObject); \ 00035 } 00036 00037 00038 VOID 00039 KeInitializeSemaphore ( 00040 IN PRKSEMAPHORE Semaphore, 00041 IN LONG Count, 00042 IN LONG Limit 00043 ) 00044 00045 /*++ 00046 00047 Routine Description: 00048 00049 This function initializes a kernel semaphore object. The initial 00050 count and limit of the object are set to the specified values. 00051 00052 Arguments: 00053 00054 Semaphore - Supplies a pointer to a dispatcher object of type 00055 semaphore. 00056 00057 Count - Supplies the initial count value to be assigned to the 00058 semaphore. 00059 00060 Limit - Supplies the maximum count value that the semaphore 00061 can attain. 00062 00063 Return Value: 00064 00065 None. 00066 00067 --*/ 00068 00069 { 00070 00071 // 00072 // Initialize standard dispatcher object header and set initial 00073 // count and maximum count values. 00074 // 00075 00076 Semaphore->Header.Type = SemaphoreObject; 00077 Semaphore->Header.Size = sizeof(KSEMAPHORE) / sizeof(LONG); 00078 Semaphore->Header.SignalState = Count; 00079 InitializeListHead(&Semaphore->Header.WaitListHead); 00080 Semaphore->Limit = Limit; 00081 return; 00082 } 00083 00084 LONG 00085 KeReadStateSemaphore ( 00086 IN PRKSEMAPHORE Semaphore 00087 ) 00088 00089 /*++ 00090 00091 Routine Description: 00092 00093 This function reads the current signal state of a semaphore object. 00094 00095 Arguments: 00096 00097 Semaphore - Supplies a pointer to a dispatcher object of type 00098 semaphore. 00099 00100 Return Value: 00101 00102 The current signal state of the semaphore object. 00103 00104 --*/ 00105 00106 { 00107 00108 ASSERT_SEMAPHORE( Semaphore ); 00109 00110 // 00111 // Return current signal state of semaphore object. 00112 // 00113 00114 return Semaphore->Header.SignalState; 00115 } 00116 00117 LONG 00118 KeReleaseSemaphore ( 00119 IN PRKSEMAPHORE Semaphore, 00120 IN KPRIORITY Increment, 00121 IN LONG Adjustment, 00122 IN BOOLEAN Wait 00123 ) 00124 00125 /*++ 00126 00127 Routine Description: 00128 00129 This function releases a semaphore by adding the specified adjustment 00130 value to the current semaphore count and attempts to satisfy as many 00131 Waits as possible. The previous signal state of the semaphore object 00132 is returned as the function value. 00133 00134 Arguments: 00135 00136 Semaphore - Supplies a pointer to a dispatcher object of type 00137 semaphore. 00138 00139 Increment - Supplies the priority increment that is to be applied 00140 if releasing the semaphore causes a Wait to be satisfied. 00141 00142 Adjustment - Supplies value that is to be added to the current 00143 semaphore count. 00144 00145 Wait - Supplies a boolean value that signifies whether the call to 00146 KeReleaseSemaphore will be immediately followed by a call to one 00147 of the kernel Wait functions. 00148 00149 Return Value: 00150 00151 The previous signal state of the semaphore object. 00152 00153 --*/ 00154 00155 { 00156 00157 LONG NewState; 00158 KIRQL OldIrql; 00159 LONG OldState; 00160 PRKTHREAD Thread; 00161 00162 ASSERT_SEMAPHORE( Semaphore ); 00163 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00164 00165 // 00166 // Raise IRQL to dispatcher level and lock dispatcher database. 00167 // 00168 00169 KiLockDispatcherDatabase(&OldIrql); 00170 00171 // 00172 // Capture the current signal state of the semaphore object and 00173 // compute the new count value. 00174 // 00175 00176 OldState = Semaphore->Header.SignalState; 00177 NewState = OldState + Adjustment; 00178 00179 // 00180 // If the new state value is greater than the limit or a carry occurs, 00181 // then unlock the dispatcher database, and raise an exception. 00182 // 00183 00184 if ((NewState > Semaphore->Limit) || (NewState < OldState)) { 00185 KiUnlockDispatcherDatabase(OldIrql); 00186 ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); 00187 } 00188 00189 // 00190 // Set the new signal state of the semaphore object and set the wait 00191 // next value. If the previous signal state was Not-Signaled (i.e. 00192 // the count was zero), and the wait queue is not empty, then attempt 00193 // to satisfy as many Waits as possible. 00194 // 00195 00196 Semaphore->Header.SignalState = NewState; 00197 if ((OldState == 0) && (IsListEmpty(&Semaphore->Header.WaitListHead) == FALSE)) { 00198 KiWaitTest(Semaphore, Increment); 00199 } 00200 00201 // 00202 // If the value of the Wait argument is TRUE, then return to the 00203 // caller with IRQL raised and the dispatcher database locked. Else 00204 // release the dispatcher database lock and lower IRQL to its 00205 // previous value. 00206 // 00207 00208 if (Wait != FALSE) { 00209 Thread = KeGetCurrentThread(); 00210 Thread->WaitNext = Wait; 00211 Thread->WaitIrql = OldIrql; 00212 00213 } else { 00214 KiUnlockDispatcherDatabase(OldIrql); 00215 } 00216 00217 // 00218 // Return previous signal state of sempahore object. 00219 // 00220 00221 return OldState; 00222 }

Generated on Sat May 15 19:41:45 2004 for test by doxygen 1.3.7