Explorar el Código

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

Karoly Balogh hace 3 años
padre
commit
3c5d6e7224
Se han modificado 1 ficheros con 28 adiciones y 7 borrados
  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}