Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-30 08:46:18

0001 /*
0002     Copyright (c) 2005-2021 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
0015 */
0016 
0017 #ifndef __TBB_detail__rtm_rw_mutex_H
0018 #define __TBB_detail__rtm_rw_mutex_H
0019 
0020 #include "_assert.h"
0021 #include "_utils.h"
0022 #include "../spin_rw_mutex.h"
0023 
0024 #include <atomic>
0025 
0026 namespace tbb {
0027 namespace detail {
0028 
0029 namespace r1 {
0030 struct rtm_rw_mutex_impl;
0031 }
0032 
0033 namespace d1 {
0034 
0035 constexpr std::size_t speculation_granularity = 64;
0036 #if _MSC_VER && !defined(__INTEL_COMPILER)
0037     // Suppress warning: structure was padded due to alignment specifier
0038     #pragma warning (push)
0039     #pragma warning (disable: 4324)
0040 #endif
0041 
0042 //! Fast, unfair, spinning speculation-enabled reader-writer lock with backoff and writer-preference
0043 /** @ingroup synchronization */
0044 class alignas(max_nfs_size) rtm_rw_mutex : private spin_rw_mutex {
0045     friend struct r1::rtm_rw_mutex_impl;
0046 private:
0047     enum class rtm_type {
0048         rtm_not_in_mutex,
0049         rtm_transacting_reader,
0050         rtm_transacting_writer,
0051         rtm_real_reader,
0052         rtm_real_writer
0053     };
0054 public:
0055     //! Constructors
0056     rtm_rw_mutex() noexcept : write_flag(false) {
0057         create_itt_sync(this, "tbb::speculative_spin_rw_mutex", "");
0058     }
0059 
0060     //! Destructor
0061     ~rtm_rw_mutex() = default;
0062 
0063     //! Represents acquisition of a mutex.
0064     class scoped_lock {
0065         friend struct r1::rtm_rw_mutex_impl;
0066     public:
0067         //! Construct lock that has not acquired a mutex.
0068         /** Equivalent to zero-initialization of *this. */
0069         constexpr scoped_lock() : m_mutex(nullptr), m_transaction_state(rtm_type::rtm_not_in_mutex) {}
0070 
0071         //! Acquire lock on given mutex.
0072         scoped_lock(rtm_rw_mutex& m, bool write = true) : m_mutex(nullptr), m_transaction_state(rtm_type::rtm_not_in_mutex) {
0073             acquire(m, write);
0074         }
0075 
0076         //! Release lock (if lock is held).
0077         ~scoped_lock() {
0078             if(m_transaction_state != rtm_type::rtm_not_in_mutex) {
0079                 release();
0080             }
0081         }
0082 
0083         //! No Copy
0084         scoped_lock(const scoped_lock&) = delete;
0085         scoped_lock& operator=(const scoped_lock&) = delete;
0086 
0087         //! Acquire lock on given mutex.
0088         inline void acquire(rtm_rw_mutex& m, bool write = true);
0089 
0090         //! Try acquire lock on given mutex.
0091         inline bool try_acquire(rtm_rw_mutex& m, bool write = true);
0092 
0093         //! Release lock
0094         inline void release();
0095 
0096         //! Upgrade reader to become a writer.
0097         /** Returns whether the upgrade happened without releasing and re-acquiring the lock */
0098         inline bool upgrade_to_writer();
0099 
0100         //! Downgrade writer to become a reader.
0101         inline bool downgrade_to_reader();
0102 
0103         inline bool is_writer() const;
0104     private:
0105         rtm_rw_mutex* m_mutex;
0106         rtm_type m_transaction_state;
0107     };
0108 
0109     //! Mutex traits
0110     static constexpr bool is_rw_mutex = true;
0111     static constexpr bool is_recursive_mutex = false;
0112     static constexpr bool is_fair_mutex = false;
0113 
0114 private:
0115     alignas(speculation_granularity) std::atomic<bool> write_flag;
0116 };
0117 
0118 #if _MSC_VER && !defined(__INTEL_COMPILER)
0119     #pragma warning (pop) // 4324 warning
0120 #endif
0121 
0122 } // namespace d1
0123 
0124 namespace r1 {
0125     //! Internal acquire write lock.
0126     // only_speculate == true if we're doing a try_lock, else false.
0127     TBB_EXPORT void __TBB_EXPORTED_FUNC acquire_writer(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&, bool only_speculate = false);
0128     //! Internal acquire read lock.
0129     // only_speculate == true if we're doing a try_lock, else false.
0130     TBB_EXPORT void __TBB_EXPORTED_FUNC acquire_reader(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&, bool only_speculate = false);
0131     //! Internal upgrade reader to become a writer.
0132     TBB_EXPORT bool __TBB_EXPORTED_FUNC upgrade(d1::rtm_rw_mutex::scoped_lock&);
0133     //! Internal downgrade writer to become a reader.
0134     TBB_EXPORT bool __TBB_EXPORTED_FUNC downgrade(d1::rtm_rw_mutex::scoped_lock&);
0135     //! Internal try_acquire write lock.
0136     TBB_EXPORT bool __TBB_EXPORTED_FUNC try_acquire_writer(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&);
0137     //! Internal try_acquire read lock.
0138     TBB_EXPORT bool __TBB_EXPORTED_FUNC try_acquire_reader(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&);
0139     //! Internal release lock.
0140     TBB_EXPORT void __TBB_EXPORTED_FUNC release(d1::rtm_rw_mutex::scoped_lock&);
0141 }
0142 
0143 namespace d1 {
0144 //! Acquire lock on given mutex.
0145 void rtm_rw_mutex::scoped_lock::acquire(rtm_rw_mutex& m, bool write) {
0146     __TBB_ASSERT(!m_mutex, "lock is already acquired");
0147     if (write) {
0148         r1::acquire_writer(m, *this);
0149     } else {
0150         r1::acquire_reader(m, *this);
0151     }
0152 }
0153 
0154 //! Try acquire lock on given mutex.
0155 bool rtm_rw_mutex::scoped_lock::try_acquire(rtm_rw_mutex& m, bool write) {
0156     __TBB_ASSERT(!m_mutex, "lock is already acquired");
0157     if (write) {
0158         return r1::try_acquire_writer(m, *this);
0159     } else {
0160         return r1::try_acquire_reader(m, *this);
0161     }
0162 }
0163 
0164 //! Release lock
0165 void rtm_rw_mutex::scoped_lock::release() {
0166     __TBB_ASSERT(m_mutex, "lock is not acquired");
0167     __TBB_ASSERT(m_transaction_state != rtm_type::rtm_not_in_mutex, "lock is not acquired");
0168     return r1::release(*this);
0169 }
0170 
0171 //! Upgrade reader to become a writer.
0172 /** Returns whether the upgrade happened without releasing and re-acquiring the lock */
0173 bool rtm_rw_mutex::scoped_lock::upgrade_to_writer() {
0174     __TBB_ASSERT(m_mutex, "lock is not acquired");
0175     if (m_transaction_state == rtm_type::rtm_transacting_writer || m_transaction_state == rtm_type::rtm_real_writer) {
0176         return true; // Already a writer
0177     }
0178     return r1::upgrade(*this);
0179 }
0180 
0181 //! Downgrade writer to become a reader.
0182 bool rtm_rw_mutex::scoped_lock::downgrade_to_reader() {
0183     __TBB_ASSERT(m_mutex, "lock is not acquired");
0184     if (m_transaction_state == rtm_type::rtm_transacting_reader || m_transaction_state == rtm_type::rtm_real_reader) {
0185         return true; // Already a reader
0186     }
0187     return r1::downgrade(*this);
0188 }
0189 
0190 bool rtm_rw_mutex::scoped_lock::is_writer() const {
0191     __TBB_ASSERT(m_mutex, "lock is not acquired");
0192     return m_transaction_state == rtm_type::rtm_transacting_writer || m_transaction_state == rtm_type::rtm_real_writer;
0193 }
0194 
0195 #if TBB_USE_PROFILING_TOOLS
0196 inline void set_name(rtm_rw_mutex& obj, const char* name) {
0197     itt_set_sync_name(&obj, name);
0198 }
0199 #if (_WIN32||_WIN64)
0200 inline void set_name(rtm_rw_mutex& obj, const wchar_t* name) {
0201     itt_set_sync_name(&obj, name);
0202 }
0203 #endif // WIN
0204 #else
0205 inline void set_name(rtm_rw_mutex&, const char*) {}
0206 #if (_WIN32||_WIN64)
0207 inline void set_name(rtm_rw_mutex&, const wchar_t*) {}
0208 #endif // WIN
0209 #endif
0210 
0211 } // namespace d1
0212 } // namespace detail
0213 } // namespace tbb
0214 
0215 #endif // __TBB_detail__rtm_rw_mutex_H