Browse Source

LZMACompressor: Add more barriers.

Again, not sure whether or not Windows on Arm's x86 emulator is weakly-ordered.
(In a native Arm64 build, they would be needed.)

Jordan Russell 10 tháng trước cách đây
mục cha
commit
b445cf40a3

+ 11 - 3
Projects/Src/Compression.LZMACompressor.pas

@@ -355,13 +355,17 @@ begin
     if Bytes > SizeOf(Ring.Buf) - Offset then
       Bytes := SizeOf(Ring.Buf) - Offset;
 
+    { On a weakly-ordered CPU, the read of Count above must happen before
+      Buf content is read below (otherwise the content could be stale) }
+    MemoryBarrier;
+
     if AWrite then begin
       Move(P^, Ring.Buf[Offset], Bytes);
-      InterlockedExchangeAdd(Ring.Count, Bytes);
+      InterlockedExchangeAdd(Ring.Count, Bytes);  { full barrier }
     end
     else begin
       Move(Ring.Buf[Offset], P^, Bytes);
-      InterlockedExchangeAdd(Ring.Count, -Bytes);
+      InterlockedExchangeAdd(Ring.Count, -Bytes);  { full barrier }
     end;
     if Offset + Bytes = SizeOf(Ring.Buf) then
       Offset := 0
@@ -403,8 +407,12 @@ begin
     if Bytes > SizeOf(Ring.Buf) - Ring.ReaderOffset then
       Bytes := SizeOf(Ring.Buf) - Ring.ReaderOffset;
 
+    { On a weakly-ordered CPU, the read of Count above must happen before
+      Buf content is read below (otherwise the content could be stale) }
+    MemoryBarrier;
+
     AWriteProc(Ring.Buf[Ring.ReaderOffset], Bytes);
-    InterlockedExchangeAdd(Ring.Count, -Bytes);
+    InterlockedExchangeAdd(Ring.Count, -Bytes);  { full barrier }
     if Ring.ReaderOffset + Bytes = SizeOf(Ring.Buf) then
       Ring.ReaderOffset := 0
     else

+ 6 - 2
Projects/Src/Compression.LZMACompressor/islzma/islzma_exe.c

@@ -96,12 +96,16 @@ static Longint RingBufferInternalWriteOrRead(struct TLZMACompressorRingBuffer *R
 			Bytes = (Longint)sizeof(Ring->Buf) - *Offset;
 		}
 
+		/* On a weakly-ordered CPU, the read of Count above must happen before
+		   Buf content is read below (otherwise the content could be stale) */
+		MemoryBarrier();
+
 		if (AWrite) {
 			memcpy(&Ring->Buf[*Offset], P, Bytes);
-			InterlockedExchangeAdd(&Ring->Count, Bytes);
+			InterlockedExchangeAdd(&Ring->Count, Bytes);  /* full barrier */
 		} else {
 			memcpy(P, &Ring->Buf[*Offset], Bytes);
-			InterlockedExchangeAdd(&Ring->Count, -Bytes);
+			InterlockedExchangeAdd(&Ring->Count, -Bytes);  /* full barrier */
 		}
 		if (*Offset + Bytes == sizeof(Ring->Buf)) {
 			*Offset = 0;