1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 #include "platform.h"
7 #include "intrinsics.h"
8 #include "atomic.h"
9 
10 namespace embree
11 {
12   /*! system mutex */
13   class MutexSys {
14     friend struct ConditionImplementation;
15   public:
16     MutexSys();
17     ~MutexSys();
18 
19   private:
20     MutexSys (const MutexSys& other) DELETED; // do not implement
21     MutexSys& operator= (const MutexSys& other) DELETED; // do not implement
22 
23   public:
24     void lock();
25     bool try_lock();
26     void unlock();
27 
28   protected:
29     void* mutex;
30   };
31 
32   /*! spinning mutex */
33   class SpinLock
34   {
35   public:
36 
SpinLock()37     SpinLock ()
38       : flag(false) {}
39 
isLocked()40     __forceinline bool isLocked() {
41       return flag.load();
42     }
43 
lock()44     __forceinline void lock()
45     {
46       while (true)
47       {
48         while (flag.load())
49         {
50           _mm_pause();
51           _mm_pause();
52         }
53 
54         bool expected = false;
55         if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire))
56           break;
57       }
58     }
59 
try_lock()60     __forceinline bool try_lock()
61     {
62       bool expected = false;
63       if (flag.load() != expected) {
64         return false;
65       }
66       return flag.compare_exchange_strong(expected,true,std::memory_order_acquire);
67     }
68 
unlock()69     __forceinline void unlock() {
70       flag.store(false,std::memory_order_release);
71     }
72 
wait_until_unlocked()73     __forceinline void wait_until_unlocked()
74     {
75       while(flag.load())
76       {
77         _mm_pause();
78         _mm_pause();
79       }
80     }
81 
82   public:
83     atomic<bool> flag;
84   };
85 
86   /*! safe mutex lock and unlock helper */
87   template<typename Mutex> class Lock {
88   public:
Lock(Mutex & mutex)89     Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); }
Lock(Mutex & mutex,bool locked)90     Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {}
~Lock()91     ~Lock() { if (locked) mutex.unlock(); }
lock()92     __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); }
isLocked()93     __forceinline bool isLocked() const { return locked; }
94   protected:
95     Mutex& mutex;
96     bool locked;
97   };
98 }
99