Browse Source

* m68k: implement basic support for interlocked functions using a TAS based global spinlock on CPUs which don't have the CAS instruction

Karoly Balogh 3 years ago
parent
commit
3c5d6e7224
1 changed files with 28 additions and 7 deletions
  1. 28 7
      rtl/m68k/m68k.inc

+ 28 - 7
rtl/m68k/m68k.inc

@@ -467,6 +467,24 @@ end;
 {$endif}
 
 {$IFNDEF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}
+{$IFNDEF CPUM68K_HAS_CAS}
+var
+  spinLock: byte;
+
+procedure getSpinLock; assembler; nostackframe;
+asm
+  lea.l spinlock,a0
+@loop:
+  tas (a0)
+  bne @loop
+end;
+
+procedure releaseSpinLock; assembler; nostackframe;
+asm
+  move.b #0,spinlock
+end;
+{$ENDIF}
+
 function InterLockedDecrement (var Target: longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
@@ -481,13 +499,13 @@ function InterLockedDecrement (var Target: longint) : longint;
   end;
 {$ELSE}
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Dec(Target);
     Result := Target;
+    releaseSpinLock;
   end;
 {$ENDIF}
 
-
 function InterLockedIncrement (var Target: longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
@@ -502,9 +520,10 @@ function InterLockedIncrement (var Target: longint) : longint;
   end;
 {$ELSE}
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Inc(Target);
     Result := Target;
+    releaseSpinLock;
   end;
 {$ENDIF}
 
@@ -520,13 +539,13 @@ function InterLockedExchange (var Target: longint;Source : longint) : longint;
   end;
 {$ELSE}
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     Target := Source;
+    releaseSpinLock;
   end;
 {$ENDIF}
 
-
 function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
 {$IFDEF CPUM68K_HAS_CAS}
   register; assembler;
@@ -541,9 +560,10 @@ function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint
   end;
 {$ELSE}
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     Target := Target + Source;
+    releaseSpinLock;
   end;
 {$ENDIF}
 
@@ -558,10 +578,11 @@ function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comp
   end;
 {$ELSE}
   begin
-  {$warning FIX ME}
+    getSpinLock;
     Result := Target;
     if Target = Comperand then
       Target := NewValue;
+    releaseSpinLock;
   end;
 {$ENDIF}
 {$ENDIF FPC_SYSTEM_HAS_INTERLOCKEDFUNCS}