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
));
40 NdisAcquireReadWriteLock(
41 IN PNDIS_RW_LOCK Lock
,
43 IN PLOCK_STATE LockState
)
52 UCHAR ProcessorNumber
;
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 KefAcquireSpinLockAtDpcLevel(&Lock
->SpinLock
);
85 Lock
->RefCount
[KeGetCurrentProcessorNumber()].RefCount
++;
86 KefReleaseSpinLockFromDpcLevel(&Lock
->SpinLock
);
90 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 KfReleaseSpinLock(&Lock
->SpinLock
, LockState
->OldIrql
);
133 #undef NdisAcquireSpinLock
137 IN PNDIS_SPIN_LOCK SpinLock
)
139 * FUNCTION: Acquires a spin lock for exclusive access to a resource
141 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
144 KeAcquireSpinLock(&SpinLock
->SpinLock
, &SpinLock
->OldIrql
);
151 #undef NdisAllocateSpinLock
154 NdisAllocateSpinLock(
155 IN PNDIS_SPIN_LOCK SpinLock
)
157 * FUNCTION: Initializes for an NDIS spin lock
159 * SpinLock = Pointer to an NDIS spin lock structure
162 KeInitializeSpinLock(&SpinLock
->SpinLock
);
169 #undef NdisDprAcquireSpinLock
172 NdisDprAcquireSpinLock(
173 IN PNDIS_SPIN_LOCK SpinLock
)
175 * FUNCTION: Acquires a spin lock from IRQL DISPATCH_LEVEL
177 * SpinLock = Pointer to the initialized NDIS spin lock to be acquired
180 KeAcquireSpinLockAtDpcLevel(&SpinLock
->SpinLock
);
181 SpinLock
->OldIrql
= DISPATCH_LEVEL
;
188 #undef NdisDprReleaseSpinLock
191 NdisDprReleaseSpinLock(
192 IN PNDIS_SPIN_LOCK SpinLock
)
194 * FUNCTION: Releases an acquired spin lock from IRQL DISPATCH_LEVEL
196 * SpinLock = Pointer to the acquired NDIS spin lock to be released
199 KeReleaseSpinLockFromDpcLevel(&SpinLock
->SpinLock
);
206 #undef NdisFreeSpinLock
210 IN PNDIS_SPIN_LOCK SpinLock
)
212 * FUNCTION: Releases a spin lock initialized with NdisAllocateSpinLock
214 * SpinLock = Pointer to an initialized NDIS spin lock
217 /* Nothing to do here! */
226 NdisGetCurrentProcessorCpuUsage(
229 * FUNCTION: Returns how busy the current processor is as a percentage
231 * pCpuUsage = Pointer to a buffer to place CPU usage
244 IN PNDIS_EVENT Event
)
246 * FUNCTION: Initializes an event to be used for synchronization
248 * Event = Pointer to an NDIS event structure to be initialized
251 KeInitializeEvent(&Event
->Event
, NotificationEvent
, FALSE
);
258 #undef NdisReleaseSpinLock
262 IN PNDIS_SPIN_LOCK SpinLock
)
264 * FUNCTION: Releases a spin lock previously acquired with NdisAcquireSpinLock
266 * SpinLock = Pointer to the acquired NDIS spin lock to be released
269 KeReleaseSpinLock(&SpinLock
->SpinLock
, SpinLock
->OldIrql
);
279 IN PNDIS_EVENT Event
)
281 * FUNCTION: Clears the signaled state of an event
283 * Event = Pointer to the initialized event object to be reset
286 KeResetEvent(&Event
->Event
);
296 IN PNDIS_EVENT Event
)
298 * FUNCTION: Sets an event to a signaled state if not already signaled
300 * Event = Pointer to the initialized event object to be set
303 KeSetEvent(&Event
->Event
, IO_NO_INCREMENT
, FALSE
);
313 IN PNDIS_EVENT Event
,
316 * FUNCTION: Waits for an event to become signaled
318 * Event = Pointer to the initialized event object to wait for
319 * MsToWait = Maximum milliseconds to wait for the event to become signaled
321 * TRUE if the event is in the signaled state
324 LARGE_INTEGER Timeout
;
327 Timeout
.QuadPart
= MsToWait
* -10000LL;
329 Status
= KeWaitForSingleObject(&Event
->Event
, Executive
, KernelMode
, TRUE
, &Timeout
);
331 return (Status
== STATUS_SUCCESS
);