2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: Program control routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 3 Oct 2003 Vizzini - Formatting and minor bugfixes
21 NdisInitializeReadWriteLock(
22 IN PNDIS_RW_LOCK Lock
)
24 * FUNCTION: Initialize a NDIS_RW_LOCK
26 * Lock: pointer to the lock to initialize
31 RtlZeroMemory(Lock
, sizeof(NDIS_RW_LOCK
));
33 KeInitializeSpinLock(&Lock
->SpinLock
);
42 NdisAcquireReadWriteLock(
43 IN PNDIS_RW_LOCK Lock
,
45 IN PLOCK_STATE LockState
)
54 UCHAR ProcessorNumber
;
55 volatile UCHAR BusyLoop
;
57 ASSERT_IRQL(DISPATCH_LEVEL
);
60 if (Lock
->Context
== PsGetCurrentThread()) {
61 LockState
->LockState
= 2;
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
--; )
74 Lock
->Context
= PsGetCurrentThread();
75 LockState
->LockState
= 4;
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) {
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
);
92 Lock
->Context
= PsGetCurrentThread();
93 LockState
->LockState
= 3;
103 NdisReleaseReadWriteLock(
104 IN PNDIS_RW_LOCK Lock
,
105 IN PLOCK_STATE LockState
)
113 switch (LockState
->LockState
) {
114 case 2: /* Exclusive write lock, recursive */
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
);
124 case 4: /* Exclusive write lock */
125 Lock
->Context
= NULL
;
126 LockState
->LockState
= -1;
127 KeReleaseSpinLock(&Lock
->SpinLock
, LockState
->OldIrql
);
136 #undef NdisAcquireSpinLock
140 IN PNDIS_SPIN_LOCK SpinLock
)
142 * FUNCTION: Acquires a spin lock for exclusive access to a resource
144 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
147 KeAcquireSpinLock(&SpinLock
->SpinLock
, &SpinLock
->OldIrql
);
154 #undef NdisAllocateSpinLock
157 NdisAllocateSpinLock(
158 IN PNDIS_SPIN_LOCK SpinLock
)
160 * FUNCTION: Initializes for an NDIS spin lock
162 * SpinLock = Pointer to an NDIS spin lock structure
165 KeInitializeSpinLock(&SpinLock
->SpinLock
);
172 #undef NdisDprAcquireSpinLock
175 NdisDprAcquireSpinLock(
176 IN PNDIS_SPIN_LOCK SpinLock
)
178 * FUNCTION: Acquires a spin lock from IRQL DISPATCH_LEVEL
180 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
183 KeAcquireSpinLockAtDpcLevel(&SpinLock
->SpinLock
);
184 SpinLock
->OldIrql
= DISPATCH_LEVEL
;
191 #undef NdisDprReleaseSpinLock
194 NdisDprReleaseSpinLock(
195 IN PNDIS_SPIN_LOCK SpinLock
)
197 * FUNCTION: Releases an acquired spin lock from IRQL DISPATCH_LEVEL
199 * SpinLock = Pointer to the acquired NDIS spin lock to be released
202 KeReleaseSpinLockFromDpcLevel(&SpinLock
->SpinLock
);
209 #undef NdisFreeSpinLock
213 IN PNDIS_SPIN_LOCK SpinLock
)
215 * FUNCTION: Releases a spin lock initialized with NdisAllocateSpinLock
217 * SpinLock = Pointer to an initialized NDIS spin lock
220 /* Nothing to do here! */
230 IN PNDIS_EVENT Event
)
232 * FUNCTION: Initializes an event to be used for synchronization
234 * Event = Pointer to an NDIS event structure to be initialized
237 KeInitializeEvent(&Event
->Event
, NotificationEvent
, FALSE
);
244 #undef NdisReleaseSpinLock
248 IN PNDIS_SPIN_LOCK SpinLock
)
250 * FUNCTION: Releases a spin lock previously acquired with NdisAcquireSpinLock
252 * SpinLock = Pointer to the acquired NDIS spin lock to be released
255 KeReleaseSpinLock(&SpinLock
->SpinLock
, SpinLock
->OldIrql
);
265 IN PNDIS_EVENT Event
)
267 * FUNCTION: Clears the signaled state of an event
269 * Event = Pointer to the initialized event object to be reset
272 KeResetEvent(&Event
->Event
);
282 IN PNDIS_EVENT Event
)
284 * FUNCTION: Sets an event to a signaled state if not already signaled
286 * Event = Pointer to the initialized event object to be set
289 KeSetEvent(&Event
->Event
, IO_NO_INCREMENT
, FALSE
);
299 IN PNDIS_EVENT Event
,
302 * FUNCTION: Waits for an event to become signaled
304 * Event = Pointer to the initialized event object to wait for
305 * MsToWait = Maximum milliseconds to wait for the event to become signaled
307 * TRUE if the event is in the signaled state
310 LARGE_INTEGER Timeout
;
313 Timeout
.QuadPart
= Int32x32To64(MsToWait
, -10000);
315 Status
= KeWaitForSingleObject(&Event
->Event
, Executive
, KernelMode
, TRUE
, &Timeout
);
317 return (Status
== STATUS_SUCCESS
);