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

Commit

Permalink
Merge pull request #1084 from adamsaka/cas16byte
Browse files Browse the repository at this point in the history
16-Byte Cas, AtomicStore and AtomicLoad added to core.atomic.
  • Loading branch information
MartinNowak committed Jan 6, 2015
2 parents 36ed59b + c66f103 commit 19a7fd1
Showing 1 changed file with 169 additions and 0 deletions.
169 changes: 169 additions & 0 deletions src/core/atomic.d
Expand Up @@ -20,16 +20,19 @@ version( D_InlineAsm_X86 )
version = AsmX86;
version = AsmX86_32;
enum has64BitCAS = true;
enum has128BitCAS = false;
}
else version( D_InlineAsm_X86_64 )
{
version = AsmX86;
version = AsmX86_64;
enum has64BitCAS = true;
enum has128BitCAS = true;
}
else
{
enum has64BitCAS = false;
enum has128BitCAS = false;
}

private
Expand Down Expand Up @@ -286,6 +289,7 @@ else version( AsmX86_32 )
}
else static if( T.sizeof == long.sizeof && has64BitCAS )
{

//////////////////////////////////////////////////////////////////
// 8 Byte CAS on a 32-Bit Processor
//////////////////////////////////////////////////////////////////
Expand All @@ -306,7 +310,9 @@ else version( AsmX86_32 )
setz AL;
pop EBX;
pop EDI;

}

}
else
{
Expand Down Expand Up @@ -769,6 +775,61 @@ else version( AsmX86_64 )
setz AL;
}
}
else static if( T.sizeof == long.sizeof*2 && has128BitCAS)
{


//////////////////////////////////////////////////////////////////
// 16 Byte CAS on a 64-Bit Processor
//////////////////////////////////////////////////////////////////
version(Win64){
//Windows 64 calling convention uses different registers.
//DMD appears to reverse the register order.
asm pure nothrow @nogc
{
push RDI;
push RBX;
mov R9, writeThis;
mov R10, ifThis;
mov R11, here;

mov RDI, R9;
mov RBX, [RDI];
mov RCX, 8[RDI];

mov RDI, R10;
mov RAX, [RDI];
mov RDX, 8[RDI];

mov RDI, R11;
lock;
cmpxchg16b [RDI];
setz AL;
pop RBX;
pop RDI;
}

}else{

asm pure nothrow @nogc
{
push RDI;
push RBX;
lea RDI, writeThis;
mov RBX, [RDI];
mov RCX, 8[RDI];
lea RDI, ifThis;
mov RAX, [RDI];
mov RDX, 8[RDI];
mov RDI, here;
lock; // lock always needed to make this op atomic
cmpxchg16b [RDI];
setz AL;
pop RBX;
pop RDI;
}
}
}
else
{
static assert( false, "Invalid template type specified." );
Expand Down Expand Up @@ -929,6 +990,48 @@ else version( AsmX86_64 )
}
}
}
else static if( T.sizeof == long.sizeof*2 && has128BitCAS )
{
//////////////////////////////////////////////////////////////////
// 16 Byte Load on a 64-Bit Processor
//////////////////////////////////////////////////////////////////
version(Win64){
size_t[2] retVal;
asm
{
push RDI;
push RBX;
mov RDI, val;
mov RBX, 0;
mov RCX, 0;
mov RAX, 0;
mov RDX, 0;
lock; // lock always needed to make this op atomic
cmpxchg16b [RDI];
lea RDI, retVal;
mov [RDI], RAX;
mov 8[RDI], RDX;
pop RBX;
pop RDI;
}
return cast(typeof(return)) retVal;
}else{
asm pure nothrow @nogc
{
push RDI;
push RBX;
mov RBX, 0;
mov RCX, 0;
mov RAX, 0;
mov RDX, 0;
mov RDI, val;
lock; // lock always needed to make this op atomic
cmpxchg16b [RDI];
pop RBX;
pop RDI;
}
}
}
else
{
static assert( false, "Invalid template type specified." );
Expand Down Expand Up @@ -1043,6 +1146,53 @@ else version( AsmX86_64 )
}
}
}
else static if( T.sizeof == long.sizeof*2 && has128BitCAS )
{
//////////////////////////////////////////////////////////////////
// 16 Byte Store on a 64-Bit Processor
//////////////////////////////////////////////////////////////////
version(Win64){
asm
{
push RDI;
push RBX;
mov R9, val;
mov R10, newval;

mov RDI, R10;
mov RBX, [RDI];
mov RCX, 8[RDI];


mov RDI, R9;
mov RAX, [RDI];
mov RDX, 8[RDI];

L1: lock; // lock always needed to make this op atomic
cmpxchg16b [RDI];
jne L1;
pop RBX;
pop RDI;
}
}else{
asm pure nothrow @nogc
{
push RDI;
push RBX;
lea RDI, newval;
mov RBX, [RDI];
mov RCX, 8[RDI];
mov RDI, val;
mov RAX, [RDI];
mov RDX, 8[RDI];
L1: lock; // lock always needed to make this op atomic
cmpxchg16b [RDI];
jne L1;
pop RBX;
pop RDI;
}
}
}
else
{
static assert( false, "Invalid template type specified." );
Expand Down Expand Up @@ -1166,6 +1316,25 @@ version( unittest )
testType!(long)();
testType!(ulong)();
}

static if (has128BitCAS)
{
struct DoubleValue
{
long value1;
long value2;
}

align(16) shared DoubleValue a;
atomicStore(a, DoubleValue(1,2));
assert(a.value1 == 1 && a.value2 ==2);

while(!cas(&a, DoubleValue(1,2), DoubleValue(3,4))){}
assert(a.value1 == 3 && a.value2 ==4);

align(16) DoubleValue b = atomicLoad(a);
assert(b.value1 == 3 && b.value2 ==4);
}

shared(size_t) i;

Expand Down

0 comments on commit 19a7fd1

Please sign in to comment.