"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/druntime/import/core/internal/spinlock.d" (20 Nov 2020, 1958 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2  * SpinLock for runtime internal usage.
    3  *
    4  * Copyright: Copyright Digital Mars 2015 -.
    5  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
    6  * Authors:   Martin Nowak
    7  * Source: $(DRUNTIMESRC core/internal/_spinlock.d)
    8  */
    9 module core.internal.spinlock;
   10 
   11 import core.atomic, core.thread;
   12 
   13 shared struct SpinLock
   14 {
   15     /// for how long is the lock usually contended
   16     enum Contention : ubyte
   17     {
   18         brief,
   19         medium,
   20         lengthy,
   21     }
   22 
   23 @trusted @nogc nothrow:
   24     this(Contention contention)
   25     {
   26         this.contention = contention;
   27     }
   28 
   29     void lock()
   30     {
   31         if (cas(&val, size_t(0), size_t(1)))
   32             return;
   33         // Try to reduce the chance of another cas failure
   34         // TTAS lock (https://en.wikipedia.org/wiki/Test_and_test-and-set)
   35         immutable step = 1 << contention;
   36         while (true)
   37         {
   38             for (size_t n; atomicLoad!(MemoryOrder.raw)(val); n += step)
   39                 yield(n);
   40             if (cas(&val, size_t(0), size_t(1)))
   41                 return;
   42         }
   43     }
   44 
   45     void unlock()
   46     {
   47         atomicStore!(MemoryOrder.rel)(val, size_t(0));
   48     }
   49 
   50     /// yield with backoff
   51     void yield(size_t k)
   52     {
   53         import core.time;
   54         if (k < pauseThresh)
   55             return core.atomic.pause();
   56         else if (k < 32)
   57             return Thread.yield();
   58         Thread.sleep(1.msecs);
   59     }
   60 
   61 private:
   62     version (D_InlineAsm_X86)
   63         enum X86 = true;
   64     else version (D_InlineAsm_X86_64)
   65         enum X86 = true;
   66     else
   67         enum X86 = false;
   68 
   69     static if (X86)
   70         enum pauseThresh = 16;
   71     else
   72         enum pauseThresh = 4;
   73 
   74     size_t val;
   75     Contention contention;
   76 }
   77 
   78 // aligned to cacheline to avoid false sharing
   79 shared align(64) struct AlignedSpinLock
   80 {
   81     this(SpinLock.Contention contention) @trusted @nogc nothrow
   82     {
   83         impl = shared(SpinLock)(contention);
   84     }
   85 
   86     SpinLock impl;
   87     alias impl this;
   88 }