diff --git a/Projects/Src/Compression.LZMACompressor.pas b/Projects/Src/Compression.LZMACompressor.pas index be2f1224..46e62f7f 100644 --- a/Projects/Src/Compression.LZMACompressor.pas +++ b/Projects/Src/Compression.LZMACompressor.pas @@ -355,13 +355,17 @@ function RingBufferInternalWriteOrRead(var Ring: TLZMACompressorRingBuffer; 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 @@ function RingBufferReadToCallback(var Ring: TLZMACompressorRingBuffer; 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 diff --git a/Projects/Src/Compression.LZMACompressor/islzma/islzma_exe.c b/Projects/Src/Compression.LZMACompressor/islzma/islzma_exe.c index 0fd4f569..e780a928 100644 --- a/Projects/Src/Compression.LZMACompressor/islzma/islzma_exe.c +++ b/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;