1 //////////////////////////////////////////////////////////////////////////////// 2 // 3 // The University of Illinois/NCSA 4 // Open Source License (NCSA) 5 // 6 // Copyright (c) 2014-2015, Advanced Micro Devices, Inc. All rights reserved. 7 // 8 // Developed by: 9 // 10 // AMD Research and AMD HSA Software Development 11 // 12 // Advanced Micro Devices, Inc. 13 // 14 // www.amd.com 15 // 16 // Permission is hereby granted, free of charge, to any person obtaining a copy 17 // of this software and associated documentation files (the "Software"), to 18 // deal with the Software without restriction, including without limitation 19 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 // and/or sell copies of the Software, and to permit persons to whom the 21 // Software is furnished to do so, subject to the following conditions: 22 // 23 // - Redistributions of source code must retain the above copyright notice, 24 // this list of conditions and the following disclaimers. 25 // - Redistributions in binary form must reproduce the above copyright 26 // notice, this list of conditions and the following disclaimers in 27 // the documentation and/or other materials provided with the distribution. 28 // - Neither the names of Advanced Micro Devices, Inc, 29 // nor the names of its contributors may be used to endorse or promote 30 // products derived from this Software without specific prior written 31 // permission. 32 // 33 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 36 // THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 37 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 38 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 39 // DEALINGS WITH THE SOFTWARE. 40 // 41 //////////////////////////////////////////////////////////////////////////////// 42 43 // Library of syncronization primitives - to be added to as needed. 44 45 #ifndef HSA_RUNTIME_CORE_UTIL_LOCKS_H_ 46 #define HSA_RUNTIME_CORE_UTIL_LOCKS_H_ 47 48 #include "utils.h" 49 #include "os.h" 50 51 /// @brief: A class behaves as a lock in a scope. When trying to enter into the 52 /// critical section, creat a object of this class. After the control path goes 53 /// out of the scope, it will release the lock automatically. 54 template <class LockType> 55 class ScopedAcquire { 56 public: 57 /// @brief: When constructing, acquire the lock. 58 /// @param: lock(Input), pointer to an existing lock. ScopedAcquire(LockType * lock)59 explicit ScopedAcquire(LockType* lock) : lock_(lock), doRelease(true) { lock_->Acquire(); } 60 61 /// @brief: when destructing, release the lock. ~ScopedAcquire()62 ~ScopedAcquire() { 63 if (doRelease) lock_->Release(); 64 } 65 66 /// @brief: Release the lock early. Avoid using when possible. Release()67 void Release() { 68 lock_->Release(); 69 doRelease = false; 70 } 71 72 private: 73 LockType* lock_; 74 bool doRelease; 75 /// @brief: Disable copiable and assignable ability. 76 DISALLOW_COPY_AND_ASSIGN(ScopedAcquire); 77 }; 78 79 /// @brief: a class represents a kernel mutex. 80 /// Uses the kernel's scheduler to keep the waiting thread from being scheduled 81 /// until the lock is released (Best for long waits, though anything using 82 /// a kernel object is a long wait). 83 class KernelMutex { 84 public: KernelMutex()85 KernelMutex() { lock_ = os::CreateMutex(); } ~KernelMutex()86 ~KernelMutex() { os::DestroyMutex(lock_); } 87 Try()88 bool Try() { return os::TryAcquireMutex(lock_); } Acquire()89 bool Acquire() { return os::AcquireMutex(lock_); } Release()90 void Release() { os::ReleaseMutex(lock_); } 91 92 private: 93 os::Mutex lock_; 94 95 /// @brief: Disable copiable and assignable ability. 96 DISALLOW_COPY_AND_ASSIGN(KernelMutex); 97 }; 98 99 /// @brief: represents a spin lock. 100 /// For very short hold durations on the order of the thread scheduling 101 /// quanta or less. 102 class SpinMutex { 103 public: SpinMutex()104 SpinMutex() { lock_ = 0; } 105 Try()106 bool Try() { 107 int old = 0; 108 return lock_.compare_exchange_strong(old, 1); 109 } Acquire()110 bool Acquire() { 111 int old = 0; 112 while (!lock_.compare_exchange_strong(old, 1)) 113 { 114 old=0; 115 os::YieldThread(); 116 } 117 return true; 118 } Release()119 void Release() { lock_ = 0; } 120 121 private: 122 std::atomic<int> lock_; 123 124 /// @brief: Disable copiable and assignable ability. 125 DISALLOW_COPY_AND_ASSIGN(SpinMutex); 126 }; 127 128 class KernelEvent { 129 public: KernelEvent()130 KernelEvent() { evt_ = os::CreateOsEvent(true, true); } ~KernelEvent()131 ~KernelEvent() { os::DestroyOsEvent(evt_); } 132 IsSet()133 bool IsSet() { return os::WaitForOsEvent(evt_, 0)==0; } WaitForSet()134 bool WaitForSet() { return os::WaitForOsEvent(evt_, 0xFFFFFFFF)==0; } Set()135 void Set() { os::SetOsEvent(evt_); } Reset()136 void Reset() { os::ResetOsEvent(evt_); } 137 138 private: 139 os::EventHandle evt_; 140 141 /// @brief: Disable copiable and assignable ability. 142 DISALLOW_COPY_AND_ASSIGN(KernelEvent); 143 }; 144 145 #endif // HSA_RUNTIME_CORE_SUTIL_LOCKS_H_ 146