From a82da388bfd838ba141d3643689de68e6c48e900 Mon Sep 17 00:00:00 2001 From: mdkinney Date: Fri, 30 Nov 2007 02:33:37 +0000 Subject: 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 --- MdePkg/Library/BaseLib/Synchronization.c | 63 +++++++++++++++++++++-------- MdePkg/Library/BaseLib/SynchronizationGcc.c | 63 +++++++++++++++++++++-------- MdePkg/Library/BaseLib/SynchronizationMsc.c | 63 +++++++++++++++++++++-------- 3 files changed, 141 insertions(+), 48 deletions(-) (limited to 'MdePkg/Library') diff --git a/MdePkg/Library/BaseLib/Synchronization.c b/MdePkg/Library/BaseLib/Synchronization.c index b7c89732e0..f1565db3fd 100644 --- a/MdePkg/Library/BaseLib/Synchronization.c +++ b/MdePkg/Library/BaseLib/Synchronization.c @@ -101,15 +101,32 @@ AcquireSpinLock ( IN OUT SPIN_LOCK *SpinLock ) { - UINT64 Tick; - UINT64 Start, End; - UINT64 Timeout; + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; - Tick = 0; - Start = 0; - End = 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 ( 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 (); + 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 (); } - } - - while (!AcquireSpinLockOrFail (SpinLock)) { - CpuPause (); - ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ())); } return SpinLock; } diff --git a/MdePkg/Library/BaseLib/SynchronizationGcc.c b/MdePkg/Library/BaseLib/SynchronizationGcc.c index 1681b4cf44..4c30dbc4b1 100644 --- a/MdePkg/Library/BaseLib/SynchronizationGcc.c +++ b/MdePkg/Library/BaseLib/SynchronizationGcc.c @@ -110,15 +110,32 @@ AcquireSpinLock ( IN OUT SPIN_LOCK *SpinLock ) { - UINT64 Tick; - UINT64 Start, End; - UINT64 Timeout; + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; - Tick = 0; - Start = 0; - End = 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 ( 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 (); + 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 (); } - } - - while (!AcquireSpinLockOrFail (SpinLock)) { - CpuPause (); - ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ())); } return SpinLock; } diff --git a/MdePkg/Library/BaseLib/SynchronizationMsc.c b/MdePkg/Library/BaseLib/SynchronizationMsc.c index 9f1ec19383..0bc60259b1 100644 --- a/MdePkg/Library/BaseLib/SynchronizationMsc.c +++ b/MdePkg/Library/BaseLib/SynchronizationMsc.c @@ -112,15 +112,32 @@ AcquireSpinLock ( IN OUT SPIN_LOCK *SpinLock ) { - UINT64 Tick; - UINT64 Start, End; - UINT64 Timeout; + UINT64 Current; + UINT64 Previous; + UINT64 Total; + UINT64 Start; + UINT64 End; + UINT64 Timeout; + INT64 Cycle; + INT64 Delta; - Tick = 0; - Start = 0; - End = 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 ( 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 (); + 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 (); } - } - - while (!AcquireSpinLockOrFail (SpinLock)) { - CpuPause (); - ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ())); } return SpinLock; } -- cgit v1.2.3