mirror of https://github.com/acidanthera/audk.git
Fix timeout logic in AcquireSpinLock(). It could fail if the end time computed was larger than the roll over value of the performance counter. The timeout logic now accumulates the total time elapsed to determine if the timeout has been exceeded.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4345 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
9a6b83a4ad
commit
a82da388bf
|
@ -101,15 +101,32 @@ AcquireSpinLock (
|
|||
IN OUT SPIN_LOCK *SpinLock
|
||||
)
|
||||
{
|
||||
UINT64 Tick;
|
||||
UINT64 Start, End;
|
||||
UINT64 Current;
|
||||
UINT64 Previous;
|
||||
UINT64 Total;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT64 Timeout;
|
||||
INT64 Cycle;
|
||||
INT64 Delta;
|
||||
|
||||
Tick = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
//
|
||||
// Get the current timer value
|
||||
//
|
||||
Current = GetPerformanceCounter();
|
||||
|
||||
//
|
||||
// Initialize local variables
|
||||
//
|
||||
Start = 0;
|
||||
End = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
Tick = GetPerformanceCounter ();
|
||||
Total = 0;
|
||||
|
||||
//
|
||||
// Retrieve the performance counter properties and compute the number of performance
|
||||
// counter ticks required to reach the timeout
|
||||
//
|
||||
Timeout = DivU64x32 (
|
||||
MultU64x32 (
|
||||
GetPerformanceCounterProperties (&Start, &End),
|
||||
|
@ -117,16 +134,30 @@ AcquireSpinLock (
|
|||
),
|
||||
1000000
|
||||
);
|
||||
if (Start < End) {
|
||||
Tick += Timeout;
|
||||
} else {
|
||||
Tick -= Timeout;
|
||||
}
|
||||
Cycle = End - Start;
|
||||
if (Cycle < 0) {
|
||||
Cycle = -Cycle;
|
||||
}
|
||||
Cycle++;
|
||||
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
ASSERT (Total < Timeout);
|
||||
}
|
||||
} else {
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
return SpinLock;
|
||||
}
|
||||
|
|
|
@ -110,15 +110,32 @@ AcquireSpinLock (
|
|||
IN OUT SPIN_LOCK *SpinLock
|
||||
)
|
||||
{
|
||||
UINT64 Tick;
|
||||
UINT64 Start, End;
|
||||
UINT64 Current;
|
||||
UINT64 Previous;
|
||||
UINT64 Total;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT64 Timeout;
|
||||
INT64 Cycle;
|
||||
INT64 Delta;
|
||||
|
||||
Tick = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
//
|
||||
// Get the current timer value
|
||||
//
|
||||
Current = GetPerformanceCounter();
|
||||
|
||||
//
|
||||
// Initialize local variables
|
||||
//
|
||||
Start = 0;
|
||||
End = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
Tick = GetPerformanceCounter ();
|
||||
Total = 0;
|
||||
|
||||
//
|
||||
// Retrieve the performance counter properties and compute the number of performance
|
||||
// counter ticks required to reach the timeout
|
||||
//
|
||||
Timeout = DivU64x32 (
|
||||
MultU64x32 (
|
||||
GetPerformanceCounterProperties (&Start, &End),
|
||||
|
@ -126,16 +143,30 @@ AcquireSpinLock (
|
|||
),
|
||||
1000000
|
||||
);
|
||||
if (Start < End) {
|
||||
Tick += Timeout;
|
||||
} else {
|
||||
Tick -= Timeout;
|
||||
}
|
||||
Cycle = End - Start;
|
||||
if (Cycle < 0) {
|
||||
Cycle = -Cycle;
|
||||
}
|
||||
Cycle++;
|
||||
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
ASSERT (Total < Timeout);
|
||||
}
|
||||
} else {
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
return SpinLock;
|
||||
}
|
||||
|
|
|
@ -112,15 +112,32 @@ AcquireSpinLock (
|
|||
IN OUT SPIN_LOCK *SpinLock
|
||||
)
|
||||
{
|
||||
UINT64 Tick;
|
||||
UINT64 Start, End;
|
||||
UINT64 Current;
|
||||
UINT64 Previous;
|
||||
UINT64 Total;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT64 Timeout;
|
||||
INT64 Cycle;
|
||||
INT64 Delta;
|
||||
|
||||
Tick = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
//
|
||||
// Get the current timer value
|
||||
//
|
||||
Current = GetPerformanceCounter();
|
||||
|
||||
//
|
||||
// Initialize local variables
|
||||
//
|
||||
Start = 0;
|
||||
End = 0;
|
||||
if (PcdGet32 (PcdSpinLockTimeout) > 0) {
|
||||
Tick = GetPerformanceCounter ();
|
||||
Total = 0;
|
||||
|
||||
//
|
||||
// Retrieve the performance counter properties and compute the number of performance
|
||||
// counter ticks required to reach the timeout
|
||||
//
|
||||
Timeout = DivU64x32 (
|
||||
MultU64x32 (
|
||||
GetPerformanceCounterProperties (&Start, &End),
|
||||
|
@ -128,16 +145,30 @@ AcquireSpinLock (
|
|||
),
|
||||
1000000
|
||||
);
|
||||
if (Start < End) {
|
||||
Tick += Timeout;
|
||||
} else {
|
||||
Tick -= Timeout;
|
||||
}
|
||||
Cycle = End - Start;
|
||||
if (Cycle < 0) {
|
||||
Cycle = -Cycle;
|
||||
}
|
||||
Cycle++;
|
||||
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
ASSERT (Total < Timeout);
|
||||
}
|
||||
} else {
|
||||
while (!AcquireSpinLockOrFail (SpinLock)) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
return SpinLock;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue