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
20 NdisInitializeReadWriteLock(
21 IN PNDIS_RW_LOCK Lock
)
23 * FUNCTION: Initialize a NDIS_RW_LOCK
25 * Lock: pointer to the lock to initialize
30 RtlZeroMemory(Lock
, sizeof(NDIS_RW_LOCK
));
32 KeInitializeSpinLock(&Lock
->SpinLock
);
40 NdisAcquireReadWriteLock(
41 IN PNDIS_RW_LOCK Lock
,
43 IN PLOCK_STATE LockState
)
52 UCHAR ProcessorNumber
;
53 volatile UCHAR BusyLoop
;
55 ASSERT_IRQL(DISPATCH_LEVEL
);
58 if (Lock
->Context
== PsGetCurrentThread()) {
59 LockState
->LockState
= 2;
61 KeAcquireSpinLock(&Lock
->SpinLock
, &LockState
->OldIrql
);
62 /* Check if any other processor helds a shared lock. */
63 for (ProcessorNumber
= KeNumberProcessors
; ProcessorNumber
--; ) {
64 if (ProcessorNumber
!= KeGetCurrentProcessorNumber()) {
65 /* Wait till the shared lock is released. */
66 while (Lock
->RefCount
[ProcessorNumber
].RefCount
!= 0) {
67 for (BusyLoop
= 32; BusyLoop
--; )
72 Lock
->Context
= PsGetCurrentThread();
73 LockState
->LockState
= 4;
76 KeRaiseIrql(DISPATCH_LEVEL
, &LockState
->OldIrql
);
77 RefCount
= InterlockedIncrement((PLONG
)&Lock
->RefCount
[KeGetCurrentProcessorNumber()].RefCount
);
78 /* Racing with a exclusive write lock case. */
79 if (Lock
->SpinLock
!= 0) {
81 if (Lock
->Context
!= PsGetCurrentThread()) {
82 /* Wait for the exclusive lock to be released. */
83 Lock
->RefCount
[KeGetCurrentProcessorNumber()].RefCount
--;
84 KeAcquireSpinLockAtDpcLevel(&Lock
->SpinLock
);
85 Lock
->RefCount
[KeGetCurrentProcessorNumber()].RefCount
++;
86 KeReleaseSpinLockFromDpcLevel(&Lock
->SpinLock
);
90 Lock
->Context
= PsGetCurrentThread();
91 LockState
->LockState
= 3;
100 NdisReleaseReadWriteLock(
101 IN PNDIS_RW_LOCK Lock
,
102 IN PLOCK_STATE LockState
)
110 switch (LockState
->LockState
) {
111 case 2: /* Exclusive write lock, recursive */
114 case 3: /* Shared read lock */
115 Lock
->RefCount
[KeGetCurrentProcessorNumber()].RefCount
--;
116 LockState
->LockState
= -1;
117 if (LockState
->OldIrql
< DISPATCH_LEVEL
)
118 KeLowerIrql(LockState
->OldIrql
);
121 case 4: /* Exclusive write lock */
122 Lock
->Context
= NULL
;
123 LockState
->LockState
= -1;
124 KeReleaseSpinLock(&Lock
->SpinLock
, LockState
->OldIrql
);
132 #undef NdisAcquireSpinLock
136 IN PNDIS_SPIN_LOCK SpinLock
)
138 * FUNCTION: Acquires a spin lock for exclusive access to a resource
140 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
143 KeAcquireSpinLock(&SpinLock
->SpinLock
, &SpinLock
->OldIrql
);
149 #undef NdisAllocateSpinLock
152 NdisAllocateSpinLock(
153 IN PNDIS_SPIN_LOCK SpinLock
)
155 * FUNCTION: Initializes for an NDIS spin lock
157 * SpinLock = Pointer to an NDIS spin lock structure
160 KeInitializeSpinLock(&SpinLock
->SpinLock
);
166 #undef NdisDprAcquireSpinLock
169 NdisDprAcquireSpinLock(
170 IN PNDIS_SPIN_LOCK SpinLock
)
172 * FUNCTION: Acquires a spin lock from IRQL DISPATCH_LEVEL
174 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
177 KeAcquireSpinLockAtDpcLevel(&SpinLock
->SpinLock
);
178 SpinLock
->OldIrql
= DISPATCH_LEVEL
;
184 #undef NdisDprReleaseSpinLock
187 NdisDprReleaseSpinLock(
188 IN PNDIS_SPIN_LOCK SpinLock
)
190 * FUNCTION: Releases an acquired spin lock from IRQL DISPATCH_LEVEL
192 * SpinLock = Pointer to the acquired NDIS spin lock to be released
195 KeReleaseSpinLockFromDpcLevel(&SpinLock
->SpinLock
);
201 #undef NdisFreeSpinLock
205 IN PNDIS_SPIN_LOCK SpinLock
)
207 * FUNCTION: Releases a spin lock initialized with NdisAllocateSpinLock
209 * SpinLock = Pointer to an initialized NDIS spin lock
212 /* Nothing to do here! */
222 IN PNDIS_EVENT Event
)
224 * FUNCTION: Initializes an event to be used for synchronization
226 * Event = Pointer to an NDIS event structure to be initialized
229 KeInitializeEvent(&Event
->Event
, NotificationEvent
, FALSE
);
236 #undef NdisReleaseSpinLock
240 IN PNDIS_SPIN_LOCK SpinLock
)
242 * FUNCTION: Releases a spin lock previously acquired with NdisAcquireSpinLock
244 * SpinLock = Pointer to the acquired NDIS spin lock to be released
247 KeReleaseSpinLock(&SpinLock
->SpinLock
, SpinLock
->OldIrql
);
257 IN PNDIS_EVENT Event
)
259 * FUNCTION: Clears the signaled state of an event
261 * Event = Pointer to the initialized event object to be reset
264 KeResetEvent(&Event
->Event
);
274 IN PNDIS_EVENT Event
)
276 * FUNCTION: Sets an event to a signaled state if not already signaled
278 * Event = Pointer to the initialized event object to be set
281 KeSetEvent(&Event
->Event
, IO_NO_INCREMENT
, FALSE
);
291 IN PNDIS_EVENT Event
,
294 * FUNCTION: Waits for an event to become signaled
296 * Event = Pointer to the initialized event object to wait for
297 * MsToWait = Maximum milliseconds to wait for the event to become signaled
299 * TRUE if the event is in the signaled state
302 LARGE_INTEGER Timeout
;
305 Timeout
.QuadPart
= Int32x32To64(MsToWait
, -10000);
307 Status
= KeWaitForSingleObject(&Event
->Event
, Executive
, KernelMode
, TRUE
, &Timeout
);
309 return (Status
== STATUS_SUCCESS
);