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:
mdkinney 2007-11-30 02:33:37 +00:00
parent 9a6b83a4ad
commit a82da388bf
3 changed files with 138 additions and 45 deletions

View File

@ -101,15 +101,32 @@ AcquireSpinLock (
IN OUT SPIN_LOCK *SpinLock IN OUT SPIN_LOCK *SpinLock
) )
{ {
UINT64 Tick; UINT64 Current;
UINT64 Start, End; UINT64 Previous;
UINT64 Timeout; UINT64 Total;
UINT64 Start;
UINT64 End;
UINT64 Timeout;
INT64 Cycle;
INT64 Delta;
Tick = 0;
Start = 0;
End = 0;
if (PcdGet32 (PcdSpinLockTimeout) > 0) { if (PcdGet32 (PcdSpinLockTimeout) > 0) {
Tick = GetPerformanceCounter (); //
// Get the current timer value
//
Current = GetPerformanceCounter();
//
// Initialize local variables
//
Start = 0;
End = 0;
Total = 0;
//
// Retrieve the performance counter properties and compute the number of performance
// counter ticks required to reach the timeout
//
Timeout = DivU64x32 ( Timeout = DivU64x32 (
MultU64x32 ( MultU64x32 (
GetPerformanceCounterProperties (&Start, &End), GetPerformanceCounterProperties (&Start, &End),
@ -117,16 +134,30 @@ AcquireSpinLock (
), ),
1000000 1000000
); );
if (Start < End) { Cycle = End - Start;
Tick += Timeout; if (Cycle < 0) {
} else { Cycle = -Cycle;
Tick -= Timeout;
} }
} Cycle++;
while (!AcquireSpinLockOrFail (SpinLock)) { while (!AcquireSpinLockOrFail (SpinLock)) {
CpuPause (); 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; return SpinLock;
} }

View File

@ -110,15 +110,32 @@ AcquireSpinLock (
IN OUT SPIN_LOCK *SpinLock IN OUT SPIN_LOCK *SpinLock
) )
{ {
UINT64 Tick; UINT64 Current;
UINT64 Start, End; UINT64 Previous;
UINT64 Timeout; UINT64 Total;
UINT64 Start;
UINT64 End;
UINT64 Timeout;
INT64 Cycle;
INT64 Delta;
Tick = 0;
Start = 0;
End = 0;
if (PcdGet32 (PcdSpinLockTimeout) > 0) { if (PcdGet32 (PcdSpinLockTimeout) > 0) {
Tick = GetPerformanceCounter (); //
// Get the current timer value
//
Current = GetPerformanceCounter();
//
// Initialize local variables
//
Start = 0;
End = 0;
Total = 0;
//
// Retrieve the performance counter properties and compute the number of performance
// counter ticks required to reach the timeout
//
Timeout = DivU64x32 ( Timeout = DivU64x32 (
MultU64x32 ( MultU64x32 (
GetPerformanceCounterProperties (&Start, &End), GetPerformanceCounterProperties (&Start, &End),
@ -126,16 +143,30 @@ AcquireSpinLock (
), ),
1000000 1000000
); );
if (Start < End) { Cycle = End - Start;
Tick += Timeout; if (Cycle < 0) {
} else { Cycle = -Cycle;
Tick -= Timeout;
} }
} Cycle++;
while (!AcquireSpinLockOrFail (SpinLock)) { while (!AcquireSpinLockOrFail (SpinLock)) {
CpuPause (); 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; return SpinLock;
} }

View File

@ -112,15 +112,32 @@ AcquireSpinLock (
IN OUT SPIN_LOCK *SpinLock IN OUT SPIN_LOCK *SpinLock
) )
{ {
UINT64 Tick; UINT64 Current;
UINT64 Start, End; UINT64 Previous;
UINT64 Timeout; UINT64 Total;
UINT64 Start;
UINT64 End;
UINT64 Timeout;
INT64 Cycle;
INT64 Delta;
Tick = 0;
Start = 0;
End = 0;
if (PcdGet32 (PcdSpinLockTimeout) > 0) { if (PcdGet32 (PcdSpinLockTimeout) > 0) {
Tick = GetPerformanceCounter (); //
// Get the current timer value
//
Current = GetPerformanceCounter();
//
// Initialize local variables
//
Start = 0;
End = 0;
Total = 0;
//
// Retrieve the performance counter properties and compute the number of performance
// counter ticks required to reach the timeout
//
Timeout = DivU64x32 ( Timeout = DivU64x32 (
MultU64x32 ( MultU64x32 (
GetPerformanceCounterProperties (&Start, &End), GetPerformanceCounterProperties (&Start, &End),
@ -128,16 +145,30 @@ AcquireSpinLock (
), ),
1000000 1000000
); );
if (Start < End) { Cycle = End - Start;
Tick += Timeout; if (Cycle < 0) {
} else { Cycle = -Cycle;
Tick -= Timeout;
} }
} Cycle++;
while (!AcquireSpinLockOrFail (SpinLock)) { while (!AcquireSpinLockOrFail (SpinLock)) {
CpuPause (); 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; return SpinLock;
} }