Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 1e50000

Browse files
committed
Fix Issue 20844 - Insufficient alignment check for 16-bytes CAS on x86_64
1 parent 48082ac commit 1e50000

File tree

1 file changed

+47
-31
lines changed

1 file changed

+47
-31
lines changed

src/core/atomic.d

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -593,14 +593,12 @@ in (atomicValueIsProperlyAligned(val))
593593

594594
version (D_InlineAsm_X86)
595595
{
596-
version = AsmX86;
597596
enum has64BitXCHG = false;
598597
enum has64BitCAS = true;
599598
enum has128BitCAS = false;
600599
}
601600
else version (D_InlineAsm_X86_64)
602601
{
603-
version = AsmX86;
604602
enum has64BitXCHG = true;
605603
enum has64BitCAS = true;
606604
enum has128BitCAS = true;
@@ -621,36 +619,32 @@ else
621619

622620
private
623621
{
624-
version (AsmX86)
622+
bool atomicValueIsProperlyAligned(T)(ref T val) pure nothrow @nogc @trusted
623+
{
624+
return atomicPtrIsProperlyAligned(&val);
625+
}
626+
627+
bool atomicPtrIsProperlyAligned(T)(T* ptr) pure nothrow @nogc @safe
625628
{
626629
// NOTE: Strictly speaking, the x86 supports atomic operations on
627630
// unaligned values. However, this is far slower than the
628631
// common case, so such behavior should be prohibited.
629-
bool atomicValueIsProperlyAligned(T)(ref T val) pure nothrow @nogc @trusted
630-
{
631-
return atomicPtrIsProperlyAligned(&val);
632-
}
633-
634-
bool atomicPtrIsProperlyAligned(T)(T* ptr) pure nothrow @nogc @safe
632+
static if (T.sizeof > size_t.sizeof)
635633
{
636-
// NOTE: 32 bit x86 systems support 8 byte CAS, which only requires
637-
// 4 byte alignment, so use size_t as the align type here.
638-
static if (T.sizeof > size_t.sizeof)
634+
version (X86)
635+
{
636+
// cmpxchg8b only requires 4-bytes alignment
639637
return cast(size_t)ptr % size_t.sizeof == 0;
638+
}
640639
else
640+
{
641+
// e.g., x86_64 cmpxchg16b requires 16-bytes alignment
641642
return cast(size_t)ptr % T.sizeof == 0;
643+
}
642644
}
643-
}
644-
else
645-
{
646-
bool atomicValueIsProperlyAligned(T)(ref T val) pure nothrow @nogc @trusted
647-
{
648-
return true;
649-
}
650-
651-
bool atomicPtrIsProperlyAligned(T)(T*) pure nothrow @nogc @safe
645+
else
652646
{
653-
return true;
647+
return cast(size_t)ptr % T.sizeof == 0;
654648
}
655649
}
656650

@@ -824,6 +818,15 @@ private
824818

825819
version (CoreUnittest)
826820
{
821+
version (D_LP64)
822+
{
823+
enum hasDWCAS = has128BitCAS;
824+
}
825+
else
826+
{
827+
enum hasDWCAS = has64BitCAS;
828+
}
829+
827830
void testXCHG(T)(T val) pure nothrow @nogc @trusted
828831
in
829832
{
@@ -1003,15 +1006,6 @@ version (CoreUnittest)
10031006
assert(b.value1 == 3 && b.value2 ==4);
10041007
}
10051008

1006-
version (D_LP64)
1007-
{
1008-
enum hasDWCAS = has128BitCAS;
1009-
}
1010-
else
1011-
{
1012-
enum hasDWCAS = has64BitCAS;
1013-
}
1014-
10151009
static if (hasDWCAS)
10161010
{
10171011
static struct List { size_t gen; List* next; }
@@ -1032,6 +1026,28 @@ version (CoreUnittest)
10321026
assert(cast(uint) s1.b == 4);
10331027
}
10341028

1029+
// https://issues.dlang.org/show_bug.cgi?id=20844
1030+
static if (hasDWCAS)
1031+
{
1032+
debug: // tests CAS in-contract
1033+
1034+
pure nothrow unittest
1035+
{
1036+
import core.exception : AssertError;
1037+
1038+
align(16) shared ubyte[2 * size_t.sizeof + 1] data;
1039+
auto misalignedPointer = cast(size_t[2]*) &data[1];
1040+
size_t[2] x;
1041+
1042+
try
1043+
cas(misalignedPointer, x, x);
1044+
catch (AssertError)
1045+
return;
1046+
1047+
assert(0, "should have failed");
1048+
}
1049+
}
1050+
10351051
@betterC pure nothrow unittest
10361052
{
10371053
static struct S { int val; }

0 commit comments

Comments
 (0)