rewrite SpinLock to still work without the need to accidentally disable optimizations for a large part of the classes unit

git-svn-id: trunk@27864 -
This commit is contained in:
Károly Balogh 2014-06-06 11:05:57 +00:00
parent d3bb0d4a17
commit e89669bedc

View File

@ -83,6 +83,11 @@ var
{ this list holds all instances of external threads that need to be freed at { this list holds all instances of external threads that need to be freed at
the end of the program } the end of the program }
ExternalThreads: TThreadList; ExternalThreads: TThreadList;
{ this must be a global var, otherwise unwanted optimizations might happen in
TThread.SpinWait() }
SpinWaitDummy: LongWord;
threadvar threadvar
{ the instance of the current thread; in case of an external thread this is { the instance of the current thread; in case of an external thread this is
Nil until TThread.GetCurrentThread was called once (the RTLs need to ensure Nil until TThread.GetCurrentThread was called once (the RTLs need to ensure
@ -572,15 +577,23 @@ end;
class procedure TThread.SpinWait(aIterations: LongWord); class procedure TThread.SpinWait(aIterations: LongWord);
var
i: LongWord;
begin begin
{ yes, it's just a simple busy wait to burn some cpu cycles... and as the job { yes, it's just a simple busy wait to burn some cpu cycles... and as the job
of this loop is to burn CPU cycles we switch off any optimizations that of this loop is to burn CPU cycles we switch off any optimizations that
could interfere with this (e.g. loop unrolling) } could interfere with this (e.g. loop unrolling) }
{$PUSH} { Do *NOT* do $PUSH, $OPTIMIZATIONS OFF, <code>, $POP because optimization is
{$OPTIMIZATION OFF} not a local switch, which means $PUSH/POP doesn't affect it, so that turns
while aIterations > 0 do off *ALL* optimizations for code below this point. Thanks to this we shipped
Dec(aIterations); large parts of the classes unit with optimizations off between 2012-12-27
{$POP} and 2014-06-06.
Instead, use a global var for the spinlock, because that is always handled
as volatile, so the access won't be optimized away by the compiler. (KB) }
for i:=1 to aIterations do
begin
Inc(SpinWaitDummy); // SpinWaitDummy *MUST* be global
end;
end; end;