Edit

kc3-lang/angle/src/common/Spinlock.h

Branch :

  • Show log

    Commit

  • Author : John Plate
    Date : 2021-06-17 09:29:29
    Hash : 44a5c913
    Message : CL: Make CL front end and back end thread-safe Add locking to all mutable variables of the CL objects in the front end and pass-through back end to make them thread-safe. This fixes a crash in a multi-threaded CTS test. Bug: angleproject:6015 Change-Id: I1d6471c851217639411c434c82acd32d14035291 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2967468 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/common/Spinlock.h
  • //
    // Copyright 2021 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // Spinlock.h:
    //   Spinlock is a lock that loops actively until it gets the resource.
    //   Only use it when the lock will be granted in reasonably short time.
    
    #ifndef COMMON_SPINLOCK_H_
    #define COMMON_SPINLOCK_H_
    
    #include <atomic>
    
    // TODO(jplate) Add pause for ARM, http://anglebug.com:6067
    #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
    extern "C" void _mm_pause();
    #    pragma intrinsic(_mm_pause)
    #    define ANGLE_SMT_PAUSE() _mm_pause()
    #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
    #    define ANGLE_SMT_PAUSE() __asm__ __volatile__("pause;")
    #else
    #    define ANGLE_SMT_PAUSE() static_cast<void>(0)
    #endif
    
    namespace angle
    {
    
    class Spinlock
    {
      public:
        Spinlock() noexcept;
    
        bool try_lock() noexcept;
        void lock() noexcept;
        void unlock() noexcept;
    
      private:
        std::atomic_bool mLock;
    };
    
    inline Spinlock::Spinlock() noexcept : mLock(false) {}
    
    inline bool Spinlock::try_lock() noexcept
    {
        // Relaxed check first to prevent unnecessary cache misses.
        return !mLock.load(std::memory_order_relaxed) &&
               !mLock.exchange(true, std::memory_order_acquire);
    }
    
    inline void Spinlock::lock() noexcept
    {
        while (mLock.exchange(true, std::memory_order_acquire))
        {
            // Relaxed wait to prevent unnecessary cache misses.
            while (mLock.load(std::memory_order_relaxed))
            {
                // Optimization for simultaneous multithreading.
                ANGLE_SMT_PAUSE();
            }
        }
    }
    
    inline void Spinlock::unlock() noexcept
    {
        mLock.store(false, std::memory_order_release);
    }
    
    }  // namespace angle
    
    #endif  // COMMON_SPINLOCK_H_