diff --git a/changelog/atomic_cas.dd b/changelog/atomic_cas.dd index 4a18661ddb..efecff0ec8 100644 --- a/changelog/atomic_cas.dd +++ b/changelog/atomic_cas.dd @@ -1,4 +1,4 @@ -Added overloads for `core.atomic.cas` which don't discard their result. +Added overloads for `core.atomic : cas` which don't discard their result -Existing `core.atomic.cas` functions discard the result, which make it impossible to implement certain operations. +Existing `core.atomic : cas` functions discard the result, which make it impossible to implement certain operations. A new set of overloads was added which take `ifThis` by pointer and write the result back to the argument. diff --git a/changelog/atomic_exchange.dd b/changelog/atomic_exchange.dd index 12beb3b1db..cb69ca6484 100644 --- a/changelog/atomic_exchange.dd +++ b/changelog/atomic_exchange.dd @@ -1,3 +1,3 @@ -Added `core.atomic.atomicExchange`. +Added `core.atomic : atomicExchange` -Added missing `core.atomic.atomicExchange` function to the atomic suite. +Added missing `atomicExchange` function to the atomic suite. diff --git a/changelog/std_string.dd b/changelog/std_string.dd index efae530954..f3a7b38ef3 100644 --- a/changelog/std_string.dd +++ b/changelog/std_string.dd @@ -1,6 +1,6 @@ -Added `core.stdcpp.string`. +Added `core.stdcpp : string` -Added `core.stdcpp.string`, which links against C++ `std::basic_string` +Added `core.stdcpp : string`, which links against C++ `std::basic_string`. Known issues: diff --git a/changelog/std_vector.dd b/changelog/std_vector.dd index b8c940d147..e9399d621d 100644 --- a/changelog/std_vector.dd +++ b/changelog/std_vector.dd @@ -1,3 +1,3 @@ -Added `core.stdcpp.vector`. +Added `core.stdcpp : vector` -Added `core.stdcpp.vector`, which links against C++ `std::vector` +Added `core.stdcpp : vector`, which links against C++ `std::vector`. diff --git a/src/core/atomic.d b/src/core/atomic.d index d47b876aa7..eec6e86f70 100644 --- a/src/core/atomic.d +++ b/src/core/atomic.d @@ -466,7 +466,7 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") * true if the store occurred, false if not. */ bool casWeak(MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V)(T* here, T* ifThis, V writeThis) pure nothrow @nogc @trusted -if (!is(T == shared S, S) && !is(V == shared U, U)) + if (!is(T == shared S, S) && !is(V == shared U, U)) in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") { // resolve implicit conversions @@ -483,7 +483,7 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") /// Ditto bool casWeak(MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V1,V2)(shared(T)* here, V1* ifThis, V2 writeThis) pure nothrow @nogc @trusted -if (!is(T == class) && (is(T : V1) || is(shared T : V1))) + if (!is(T == class) && (is(T : V1) || is(shared T : V1))) in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") { static if (is (V1 == shared U1, U1)) @@ -508,7 +508,7 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") /// Ditto bool casWeak(MemoryOrder succ = MemoryOrder.seq,MemoryOrder fail = MemoryOrder.seq,T,V)(shared(T)* here, shared(T)* ifThis, shared(V) writeThis) pure nothrow @nogc @trusted -if (is(T == class)) + if (is(T == class)) in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") { return atomicCompareExchangeWeak!(succ, fail)(cast(T*)here, cast(T*)ifThis, cast(V)writeThis); @@ -519,11 +519,20 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") * that all loads and stores before a call to this function are executed before any * loads and stores after the call. */ -void atomicFence(MemoryOrder order = MemoryOrder.seq)() nothrow @nogc @safe +void atomicFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @safe { core.internal.atomic.atomicFence!order(); } +/** + * Gives a hint to the processor that the calling thread is in a 'spin-wait' loop, + * allowing to more efficiently allocate resources. + */ +void pause() pure nothrow @nogc @safe +{ + core.internal.atomic.pause(); +} + /** * Performs the binary operation 'op' on val using 'mod' as the modifier. * diff --git a/src/core/internal/atomic.d b/src/core/internal/atomic.d index 215e992c6a..5e9207b57a 100644 --- a/src/core/internal/atomic.d +++ b/src/core/internal/atomic.d @@ -589,7 +589,7 @@ bool atomicCompareExchangeStrongNoResult(MemoryOrder succ = MemoryOrder.seq, Mem static assert (false, "Unsupported architecture."); } -void atomicFence(MemoryOrder order = MemoryOrder.seq)() nothrow @nogc @safe +void atomicFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @safe { // TODO: `mfence` should only be required for seq_cst operations, but this depends on // the compiler's backend knowledge to not reorder code inappropriately, @@ -633,7 +633,7 @@ void atomicFence(MemoryOrder order = MemoryOrder.seq)() nothrow @nogc @safe } else version (D_InlineAsm_X86_64) { - asm nothrow @nogc @trusted + asm pure nothrow @nogc @trusted { naked; mfence; @@ -645,6 +645,33 @@ void atomicFence(MemoryOrder order = MemoryOrder.seq)() nothrow @nogc @safe } } +void pause() pure nothrow @nogc @safe +{ + version (D_InlineAsm_X86) + { + asm pure nothrow @nogc @trusted + { + naked; + rep; nop; + ret; + } + } + else version (D_InlineAsm_X86_64) + { + asm pure nothrow @nogc @trusted + { + naked; +// pause; // TODO: DMD should add this opcode to its inline asm + rep; nop; + ret; + } + } + else + { + // ARM should `yield` + // other architectures? otherwise some sort of nop... + } +} private: diff --git a/src/core/internal/spinlock.d b/src/core/internal/spinlock.d index cad029d0c2..36d806ad01 100644 --- a/src/core/internal/spinlock.d +++ b/src/core/internal/spinlock.d @@ -52,7 +52,7 @@ shared struct SpinLock { import core.time; if (k < pauseThresh) - return pause(); + return core.atomic.pause(); else if (k < 32) return Thread.yield(); Thread.sleep(1.msecs); @@ -67,25 +67,9 @@ private: enum X86 = false; static if (X86) - { enum pauseThresh = 16; - void pause() - { - asm @trusted @nogc nothrow - { - // pause instruction - rep; - nop; - } - } - } else - { enum pauseThresh = 4; - void pause() - { - } - } size_t val; Contention contention;