[JSC] Enable LLInt ASM interpreter on X64 and ARM64 in non JIT configuration
[WebKit-https.git] / Source / WTF / benchmarks / ToyLocks.h
index 6f6cc2b..03f75a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef ToyLocks_h
 #define ToyLocks_h
 
+#include <mutex>
 #include <thread>
 #include <wtf/Atomics.h>
 #include <wtf/Lock.h>
 #include <wtf/ParkingLot.h>
+#include <wtf/Threading.h>
 #include <wtf/WordLock.h>
 
+#if __has_include(<os/lock.h>)
+#include <os/lock.h>
+#define HAS_UNFAIR_LOCK
+#endif
+
+#if defined(EXTRA_LOCKS) && EXTRA_LOCKS
+#include <synchronic>
+#endif
+
 namespace {
 
 unsigned toyLockSpinLimit = 40;
@@ -48,7 +59,7 @@ public:
     void lock()
     {
         while (!m_lock.compareExchangeWeak(0, 1, std::memory_order_acquire))
-            std::this_thread::yield();
+            Thread::yield();
     }
 
     void unlock()
@@ -92,6 +103,83 @@ private:
     Atomic<unsigned> m_lock;
 };
 
+#if defined(EXTRA_LOCKS) && EXTRA_LOCKS
+class TransactionalSpinLock {
+public:
+    TransactionalSpinLock()
+    {
+        m_lock = 0;
+    }
+
+    void lock()
+    {
+        for (;;) {
+            unsigned char result;
+            unsigned expected = 0;
+            unsigned desired = 1;
+            asm volatile (
+                "xacquire; lock; cmpxchgl %3, %2\n\t"
+                "sete %1"
+                : "+a"(expected), "=q"(result), "+m"(m_lock)
+                : "r"(desired)
+                : "memory");
+            if (result)
+                return;
+            Thread::yield();
+        }
+    }
+
+    void unlock()
+    {
+        asm volatile (
+            "xrelease; movl $0, %0"
+            :
+            : "m"(m_lock)
+            : "memory");
+    }
+
+    bool isLocked() const
+    {
+        return m_lock;
+    }
+
+private:
+    unsigned m_lock;
+};
+
+class SynchronicLock {
+public:
+    SynchronicLock()
+        : m_locked(0)
+    {
+    }
+    
+    void lock()
+    {
+        for (;;) {
+            int state = 0;
+            if (m_locked.compare_exchange_weak(state, 1, std::memory_order_acquire))
+                return;
+            m_sync.wait_for_change(m_locked, state, std::memory_order_relaxed);
+        }
+    }
+    
+    void unlock()
+    {
+        m_sync.notify_one(m_locked, 0, std::memory_order_release);
+    }
+    
+    bool isLocked()
+    {
+        return m_locked.load();
+    }
+
+private:
+    std::atomic<int> m_locked;
+    std::experimental::synchronic<int> m_sync;
+};
+#endif
+
 template<typename StateType>
 class BargingLock {
 public:
@@ -134,7 +222,7 @@ private:
             if (currentState & hasParkedBit)
                 break;
             
-            std::this_thread::yield();
+            Thread::yield();
         }
         
         for (;;) {
@@ -154,11 +242,12 @@ private:
     {
         ParkingLot::unparkOne(
             &m_state,
-            [this] (ParkingLot::UnparkResult result) {
+            [this] (ParkingLot::UnparkResult result) -> intptr_t {
                 if (result.mayHaveMoreThreads)
                     m_state.store(hasParkedBit);
                 else
                     m_state.store(0);
+                return 0;
             });
     }
     
@@ -210,7 +299,7 @@ private:
             if (currentState == LockedAndParked)
                 break;
             
-            std::this_thread::yield();
+            Thread::yield();
         }
         
         for (;;) {
@@ -279,7 +368,7 @@ private:
             if (currentState == LockedAndParked)
                 break;
             
-            std::this_thread::yield();
+            Thread::yield();
         }
         
         State desiredState = Locked;
@@ -349,8 +438,8 @@ private:
             }
             
             if (m_state.compareExchangeWeak(state, state + parkedCountUnit)) {
-                bool result = ParkingLot::compareAndPark(&m_state, state + parkedCountUnit);
-                m_state.exchangeAndAdd(-parkedCountUnit);
+                bool result = ParkingLot::compareAndPark(&m_state, state + parkedCountUnit).wasUnparked;
+                m_state.exchangeAdd(-parkedCountUnit);
                 if (result)
                     return;
             }
@@ -385,6 +474,21 @@ private:
     Atomic<unsigned> m_state;
 };
 
+#ifdef HAS_UNFAIR_LOCK
+class UnfairLock {
+    os_unfair_lock l = OS_UNFAIR_LOCK_INIT;
+public:
+    void lock()
+    {
+        os_unfair_lock_lock(&l);
+    }
+    void unlock()
+    {
+        os_unfair_lock_unlock(&l);
+    }
+};
+#endif
+
 template<typename Benchmark>
 void runEverything(const char* what)
 {
@@ -392,6 +496,12 @@ void runEverything(const char* what)
         Benchmark::template run<YieldSpinLock>("YieldSpinLock");
     if (!strcmp(what, "pausespinlock") || !strcmp(what, "all"))
         Benchmark::template run<PauseSpinLock>("PauseSpinLock");
+#if defined(EXTRA_LOCKS) && EXTRA_LOCKS
+    if (!strcmp(what, "transactionalspinlock") || !strcmp(what, "all"))
+        Benchmark::template run<TransactionalSpinLock>("TransactionalSpinLock");
+    if (!strcmp(what, "synchroniclock") || !strcmp(what, "all"))
+        Benchmark::template run<SynchronicLock>("SynchronicLock");
+#endif
     if (!strcmp(what, "wordlock") || !strcmp(what, "all"))
         Benchmark::template run<WordLock>("WTFWordLock");
     if (!strcmp(what, "lock") || !strcmp(what, "all"))
@@ -410,8 +520,12 @@ void runEverything(const char* what)
         Benchmark::template run<CascadeLock<uint32_t>>("WordCascadeLock");
     if (!strcmp(what, "handofflock") || !strcmp(what, "all"))
         Benchmark::template run<HandoffLock>("HandoffLock");
+#ifdef HAS_UNFAIR_LOCK
+    if (!strcmp(what, "unfairlock") || !strcmp(what, "all"))
+        Benchmark::template run<UnfairLock>("UnfairLock");
+#endif
     if (!strcmp(what, "mutex") || !strcmp(what, "all"))
-        Benchmark::template run<Mutex>("PlatformMutex");
+        Benchmark::template run<std::mutex>("std::mutex");
 }
 
 } // anonymous namespace