mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
3.5 KiB
194 lines
3.5 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
atkwait.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the wait functions used by Atalk
|
|
|
|
Author:
|
|
|
|
Nikhil Kamkolkar (NikhilK) 8-Jun-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "atalknt.h"
|
|
|
|
//
|
|
// Local functions
|
|
//
|
|
|
|
VOID
|
|
NTWaitTimer(
|
|
INT MilliSeconds);
|
|
|
|
VOID
|
|
NTWaitSpin(
|
|
INT MilliSeconds);
|
|
|
|
|
|
VOID
|
|
NTWaitTimer(
|
|
INT MilliSeconds
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the wait routine that is called at APC/USER IRQL level. It currently
|
|
uses the KeDelayExecutionThread function, but could use a timer/block on
|
|
timer mechanism too.
|
|
|
|
Arguments:
|
|
|
|
MilliSeconds - The amount of time to wait for in milliseconds
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
LARGE_INTEGER interval;
|
|
|
|
//
|
|
// Use a the KeDelayExecutionThread routine to block for MilliSeconds
|
|
// For now, make it non-alertable
|
|
// BUGBUG: Can make this alertable, and introduce code in portable
|
|
// stack to alert it when request completes?? Worth the trouble?
|
|
//
|
|
|
|
//
|
|
// Time has to be in 100 nanosecond units
|
|
// Use relative time
|
|
//
|
|
|
|
interval.LowPart = - MilliSeconds * 10000L;
|
|
if (interval.LowPart != 0) {
|
|
interval.HighPart = -1L;
|
|
} else {
|
|
interval.HighPart = 0L;
|
|
}
|
|
|
|
KeDelayExecutionThread(
|
|
KernelMode,
|
|
FALSE, // Alertable?
|
|
&interval);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
NTWaitSpin(
|
|
INT MilliSeconds
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine used to wait for some time at DPC or higher level when
|
|
blocking is not permitted. It uses the NdisStallExecution, which spins
|
|
for that amount of time.
|
|
|
|
Arguments:
|
|
|
|
MilliSeconds - The amount of time to wait for in milliseconds
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// Use spin-wait non-blocking technique to block for MilliSeconds
|
|
//
|
|
|
|
NdisStallExecution((UINT)MilliSeconds);
|
|
return;
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
NTWaitFor(
|
|
INT HundrethsOfSecond,
|
|
BOOLEAN *StopFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine exported and called from the portable stack. Depending
|
|
on the IRQL level, it will call the appropriate functions. It does a waits
|
|
fort the specified amount of time, slicing the time up into WAIT_TIME_SLICE
|
|
units. If the StopFlag is found to be true anytime in between the waits it
|
|
immediately returns aborting the wait.
|
|
|
|
Arguments:
|
|
|
|
HundrethsOfSecond- Time to wait for in hundredths of a second units
|
|
StopFlag- If the flag is true, the wait should be aborted.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - return the value of the stop flag
|
|
|
|
--*/
|
|
{
|
|
KIRQL currentIrql;
|
|
INT milliSeconds = HundrethsOfSecond*10;
|
|
INT remainingTimeToWait;
|
|
|
|
|
|
//
|
|
// If >= dispatch level then stall, if APC or User set a timer and block
|
|
// use WAIT_TIME_SLICE as the wait interval.
|
|
//
|
|
|
|
currentIrql = KeGetCurrentIrql();
|
|
|
|
remainingTimeToWait = milliSeconds;
|
|
while (remainingTimeToWait > 0) {
|
|
|
|
//
|
|
// Do wait of TIME_SLICE return early if StopFlag is found to be set
|
|
//
|
|
|
|
if (currentIrql < DISPATCH_LEVEL) {
|
|
|
|
//
|
|
// We are running at user/apc level
|
|
//
|
|
|
|
NTWaitTimer(MIN(WAIT_TIME_SLICE, remainingTimeToWait));
|
|
|
|
} else {
|
|
|
|
//
|
|
// We are at DPC level or above
|
|
//
|
|
|
|
NTWaitSpin(MIN(WAIT_TIME_SLICE, remainingTimeToWait));
|
|
|
|
}
|
|
|
|
if (*StopFlag == TRUE) {
|
|
|
|
break;
|
|
}
|
|
|
|
remainingTimeToWait -= WAIT_TIME_SLICE;
|
|
}
|
|
|
|
return(*StopFlag);
|
|
}
|
|
|
|
|