@@ -593,14 +593,12 @@ in (atomicValueIsProperlyAligned(val))
593
593
594
594
version (D_InlineAsm_X86 )
595
595
{
596
- version = AsmX86;
597
596
enum has64BitXCHG = false ;
598
597
enum has64BitCAS = true ;
599
598
enum has128BitCAS = false ;
600
599
}
601
600
else version (D_InlineAsm_X86_64 )
602
601
{
603
- version = AsmX86;
604
602
enum has64BitXCHG = true ;
605
603
enum has64BitCAS = true ;
606
604
enum has128BitCAS = true ;
@@ -621,36 +619,32 @@ else
621
619
622
620
private
623
621
{
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
625
628
{
626
629
// NOTE: Strictly speaking, the x86 supports atomic operations on
627
630
// unaligned values. However, this is far slower than the
628
631
// 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)
635
633
{
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
639
637
return cast (size_t )ptr % size_t .sizeof == 0 ;
638
+ }
640
639
else
640
+ {
641
+ // e.g., x86_64 cmpxchg16b requires 16-bytes alignment
641
642
return cast (size_t )ptr % T.sizeof == 0 ;
643
+ }
642
644
}
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
652
646
{
653
- return true ;
647
+ return cast ( size_t )ptr % T.sizeof == 0 ;
654
648
}
655
649
}
656
650
@@ -824,6 +818,15 @@ private
824
818
825
819
version (CoreUnittest)
826
820
{
821
+ version (D_LP64 )
822
+ {
823
+ enum hasDWCAS = has128BitCAS;
824
+ }
825
+ else
826
+ {
827
+ enum hasDWCAS = has64BitCAS;
828
+ }
829
+
827
830
void testXCHG (T)(T val) pure nothrow @nogc @trusted
828
831
in
829
832
{
@@ -1003,15 +1006,6 @@ version (CoreUnittest)
1003
1006
assert (b.value1 == 3 && b.value2 == 4 );
1004
1007
}
1005
1008
1006
- version (D_LP64 )
1007
- {
1008
- enum hasDWCAS = has128BitCAS;
1009
- }
1010
- else
1011
- {
1012
- enum hasDWCAS = has64BitCAS;
1013
- }
1014
-
1015
1009
static if (hasDWCAS)
1016
1010
{
1017
1011
static struct List { size_t gen; List* next; }
@@ -1032,6 +1026,28 @@ version (CoreUnittest)
1032
1026
assert (cast (uint ) s1.b == 4 );
1033
1027
}
1034
1028
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
+
1035
1051
@betterC pure nothrow unittest
1036
1052
{
1037
1053
static struct S { int val; }
0 commit comments