[CLT2012]
[reactos.git] / drivers / network / ndis / ndis / control.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/control.c
5 * PURPOSE: Program control routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 3 Oct 2003 Vizzini - Formatting and minor bugfixes
11 */
12
13 #include "ndissys.h"
14
15 \f
16 /*
17 * @implemented
18 */
19 VOID
20 EXPORT
21 NdisInitializeReadWriteLock(
22 IN PNDIS_RW_LOCK Lock)
23 /*
24 * FUNCTION: Initialize a NDIS_RW_LOCK
25 * ARGUMENTS:
26 * Lock: pointer to the lock to initialize
27 * NOTES:
28 * NDIS 5.0
29 */
30 {
31 RtlZeroMemory(Lock, sizeof(NDIS_RW_LOCK));
32
33 KeInitializeSpinLock(&Lock->SpinLock);
34 }
35
36 \f
37 /*
38 * @implemented
39 */
40 VOID
41 EXPORT
42 NdisAcquireReadWriteLock(
43 IN PNDIS_RW_LOCK Lock,
44 IN BOOLEAN fWrite,
45 IN PLOCK_STATE LockState)
46 /*
47 * FUNCTION:
48 * ARGUMENTS:
49 * NOTES:
50 * NDIS 5.0
51 */
52 {
53 ULONG RefCount;
54 UCHAR ProcessorNumber;
55 volatile UCHAR BusyLoop;
56
57 ASSERT_IRQL(DISPATCH_LEVEL);
58
59 if (fWrite) {
60 if (Lock->Context == PsGetCurrentThread()) {
61 LockState->LockState = 2;
62 } else {
63 KeAcquireSpinLock(&Lock->SpinLock, &LockState->OldIrql);
64 /* Check if any other processor helds a shared lock. */
65 for (ProcessorNumber = KeNumberProcessors; ProcessorNumber--; ) {
66 if (ProcessorNumber != KeGetCurrentProcessorNumber()) {
67 /* Wait till the shared lock is released. */
68 while (Lock->RefCount[ProcessorNumber].RefCount != 0) {
69 for (BusyLoop = 32; BusyLoop--; )
70 ;
71 }
72 }
73 }
74 Lock->Context = PsGetCurrentThread();
75 LockState->LockState = 4;
76 }
77 } else {
78 KeRaiseIrql(DISPATCH_LEVEL, &LockState->OldIrql);
79 RefCount = InterlockedIncrement((PLONG)&Lock->RefCount[KeGetCurrentProcessorNumber()].RefCount);
80 /* Racing with a exclusive write lock case. */
81 if (Lock->SpinLock != 0) {
82 if (RefCount == 1) {
83 if (Lock->Context != PsGetCurrentThread()) {
84 /* Wait for the exclusive lock to be released. */
85 Lock->RefCount[KeGetCurrentProcessorNumber()].RefCount--;
86 KeAcquireSpinLockAtDpcLevel(&Lock->SpinLock);
87 Lock->RefCount[KeGetCurrentProcessorNumber()].RefCount++;
88 KeReleaseSpinLockFromDpcLevel(&Lock->SpinLock);
89 }
90 }
91 }
92 Lock->Context = PsGetCurrentThread();
93 LockState->LockState = 3;
94 }
95 }
96
97 \f
98 /*
99 * @implemented
100 */
101 VOID
102 EXPORT
103 NdisReleaseReadWriteLock(
104 IN PNDIS_RW_LOCK Lock,
105 IN PLOCK_STATE LockState)
106 /*
107 * FUNCTION:
108 * ARGUMENTS:
109 * NOTES:
110 * NDIS 5.0
111 */
112 {
113 switch (LockState->LockState) {
114 case 2: /* Exclusive write lock, recursive */
115 return;
116
117 case 3: /* Shared read lock */
118 Lock->RefCount[KeGetCurrentProcessorNumber()].RefCount--;
119 LockState->LockState = -1;
120 if (LockState->OldIrql < DISPATCH_LEVEL)
121 KeLowerIrql(LockState->OldIrql);
122 return;
123
124 case 4: /* Exclusive write lock */
125 Lock->Context = NULL;
126 LockState->LockState = -1;
127 KeReleaseSpinLock(&Lock->SpinLock, LockState->OldIrql);
128 return;
129 }
130 }
131
132 \f
133 /*
134 * @implemented
135 */
136 #undef NdisAcquireSpinLock
137 VOID
138 EXPORT
139 NdisAcquireSpinLock(
140 IN PNDIS_SPIN_LOCK SpinLock)
141 /*
142 * FUNCTION: Acquires a spin lock for exclusive access to a resource
143 * ARGUMENTS:
144 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
145 */
146 {
147 KeAcquireSpinLock(&SpinLock->SpinLock, &SpinLock->OldIrql);
148 }
149
150 \f
151 /*
152 * @implemented
153 */
154 #undef NdisAllocateSpinLock
155 VOID
156 EXPORT
157 NdisAllocateSpinLock(
158 IN PNDIS_SPIN_LOCK SpinLock)
159 /*
160 * FUNCTION: Initializes for an NDIS spin lock
161 * ARGUMENTS:
162 * SpinLock = Pointer to an NDIS spin lock structure
163 */
164 {
165 KeInitializeSpinLock(&SpinLock->SpinLock);
166 }
167
168 \f
169 /*
170 * @implemented
171 */
172 #undef NdisDprAcquireSpinLock
173 VOID
174 EXPORT
175 NdisDprAcquireSpinLock(
176 IN PNDIS_SPIN_LOCK SpinLock)
177 /*
178 * FUNCTION: Acquires a spin lock from IRQL DISPATCH_LEVEL
179 * ARGUMENTS:
180 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
181 */
182 {
183 KeAcquireSpinLockAtDpcLevel(&SpinLock->SpinLock);
184 SpinLock->OldIrql = DISPATCH_LEVEL;
185 }
186
187 \f
188 /*
189 * @implemented
190 */
191 #undef NdisDprReleaseSpinLock
192 VOID
193 EXPORT
194 NdisDprReleaseSpinLock(
195 IN PNDIS_SPIN_LOCK SpinLock)
196 /*
197 * FUNCTION: Releases an acquired spin lock from IRQL DISPATCH_LEVEL
198 * ARGUMENTS:
199 * SpinLock = Pointer to the acquired NDIS spin lock to be released
200 */
201 {
202 KeReleaseSpinLockFromDpcLevel(&SpinLock->SpinLock);
203 }
204
205 \f
206 /*
207 * @implemented
208 */
209 #undef NdisFreeSpinLock
210 VOID
211 EXPORT
212 NdisFreeSpinLock(
213 IN PNDIS_SPIN_LOCK SpinLock)
214 /*
215 * FUNCTION: Releases a spin lock initialized with NdisAllocateSpinLock
216 * ARGUMENTS:
217 * SpinLock = Pointer to an initialized NDIS spin lock
218 */
219 {
220 /* Nothing to do here! */
221 }
222
223
224 /*
225 * @implemented
226 */
227 VOID
228 EXPORT
229 NdisInitializeEvent(
230 IN PNDIS_EVENT Event)
231 /*
232 * FUNCTION: Initializes an event to be used for synchronization
233 * ARGUMENTS:
234 * Event = Pointer to an NDIS event structure to be initialized
235 */
236 {
237 KeInitializeEvent(&Event->Event, NotificationEvent, FALSE);
238 }
239
240
241 /*
242 * @implemented
243 */
244 #undef NdisReleaseSpinLock
245 VOID
246 EXPORT
247 NdisReleaseSpinLock(
248 IN PNDIS_SPIN_LOCK SpinLock)
249 /*
250 * FUNCTION: Releases a spin lock previously acquired with NdisAcquireSpinLock
251 * ARGUMENTS:
252 * SpinLock = Pointer to the acquired NDIS spin lock to be released
253 */
254 {
255 KeReleaseSpinLock(&SpinLock->SpinLock, SpinLock->OldIrql);
256 }
257
258
259 /*
260 * @implemented
261 */
262 VOID
263 EXPORT
264 NdisResetEvent(
265 IN PNDIS_EVENT Event)
266 /*
267 * FUNCTION: Clears the signaled state of an event
268 * ARGUMENTS:
269 * Event = Pointer to the initialized event object to be reset
270 */
271 {
272 KeResetEvent(&Event->Event);
273 }
274
275
276 /*
277 * @implemented
278 */
279 VOID
280 EXPORT
281 NdisSetEvent(
282 IN PNDIS_EVENT Event)
283 /*
284 * FUNCTION: Sets an event to a signaled state if not already signaled
285 * ARGUMENTS:
286 * Event = Pointer to the initialized event object to be set
287 */
288 {
289 KeSetEvent(&Event->Event, IO_NO_INCREMENT, FALSE);
290 }
291
292
293 /*
294 * @implemented
295 */
296 BOOLEAN
297 EXPORT
298 NdisWaitEvent(
299 IN PNDIS_EVENT Event,
300 IN UINT MsToWait)
301 /*
302 * FUNCTION: Waits for an event to become signaled
303 * ARGUMENTS:
304 * Event = Pointer to the initialized event object to wait for
305 * MsToWait = Maximum milliseconds to wait for the event to become signaled
306 * RETURNS:
307 * TRUE if the event is in the signaled state
308 */
309 {
310 LARGE_INTEGER Timeout;
311 NTSTATUS Status;
312
313 Timeout.QuadPart = Int32x32To64(MsToWait, -10000);
314
315 Status = KeWaitForSingleObject(&Event->Event, Executive, KernelMode, TRUE, &Timeout);
316
317 return (Status == STATUS_SUCCESS);
318 }
319
320 /* EOF */
321