1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H 17 #define COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H 18 19 #include <stddef.h> 20 #include <cstdint> 21 22 namespace common { 23 using StateWordType = uint64_t; 24 using MAddress = uint64_t; 25 class TypeInfo; 26 27 enum class LanguageType : uint64_t { 28 DYNAMIC = 0, 29 STATIC = 1, 30 }; 31 32 class BaseStateWord { 33 public: 34 static constexpr size_t PADDING_WIDTH = 60; 35 static constexpr size_t FORWARD_WIDTH = 2; 36 static constexpr size_t LANGUAGE_WIDTH = 2; 37 38 BaseStateWord() = default; BaseStateWord(MAddress header)39 BaseStateWord(MAddress header) : header_(header) {}; 40 41 enum class ForwardState : uint64_t { 42 NORMAL, 43 FORWARDING, 44 FORWARDED, 45 TO_VERSION 46 }; 47 SetForwarding()48 inline void SetForwarding() 49 { 50 state_.forwardState_ = ForwardState::FORWARDING; 51 } 52 IsForwarding()53 inline bool IsForwarding() const 54 { 55 return state_.forwardState_ == ForwardState::FORWARDING; 56 } 57 IsToVersion()58 inline bool IsToVersion() const 59 { 60 return state_.forwardState_ == ForwardState::TO_VERSION; 61 } 62 TryLockBaseStateWord(const BaseStateWord current)63 bool TryLockBaseStateWord(const BaseStateWord current) 64 { 65 if (current.IsForwarding()) { 66 return false; 67 } 68 BaseStateWord newState = BaseStateWord(current.GetHeader()); 69 newState.SetForwardState(ForwardState::FORWARDING); 70 return CompareExchangeHeader(current.GetHeader(), newState.GetHeader()); 71 } 72 UnlockStateWord(const ForwardState forwardState)73 void UnlockStateWord(const ForwardState forwardState) 74 { 75 do { 76 BaseStateWord current = AtomicGetBaseStateWord(); 77 BaseStateWord newState = BaseStateWord(current.GetHeader()); 78 newState.SetForwardState(forwardState); 79 if (CompareExchangeHeader(current.GetHeader(), newState.GetHeader())) { 80 return; 81 } 82 } while (true); 83 } 84 SetForwardState(ForwardState state)85 void SetForwardState(ForwardState state) 86 { 87 state_.forwardState_ = state; 88 } 89 GetForwardState()90 ForwardState GetForwardState() const 91 { 92 return state_.forwardState_; 93 } 94 GetBaseClassAddress()95 common::StateWordType GetBaseClassAddress() const 96 { 97 return state_.padding_; 98 } 99 SetFullBaseClassAddress(common::StateWordType address)100 void SetFullBaseClassAddress(common::StateWordType address) 101 { 102 state_.padding_ = address; 103 } 104 private: 105 // Little endian 106 struct State { 107 common::StateWordType padding_ : PADDING_WIDTH; 108 LanguageType language_ : LANGUAGE_WIDTH; 109 ForwardState forwardState_ : FORWARD_WIDTH; 110 }; 111 112 union { 113 State state_; 114 MAddress header_; 115 }; 116 AtomicGetBaseStateWord()117 BaseStateWord AtomicGetBaseStateWord() const 118 { 119 return BaseStateWord(AtomicGetHeader()); 120 } 121 AtomicGetHeader()122 MAddress AtomicGetHeader() const 123 { 124 return __atomic_load_n(&header_, __ATOMIC_ACQUIRE); 125 } 126 GetHeader()127 MAddress GetHeader() const { return header_; } 128 CompareExchangeHeader(MAddress expected,MAddress newState)129 bool CompareExchangeHeader(MAddress expected, MAddress newState) 130 { 131 #if defined(__x86_64__) 132 bool success = 133 __atomic_compare_exchange_n(&header_, &expected, newState, true, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); 134 #else 135 // due to "Spurious Failure" of compare_exchange_weak, compare_exchange_strong is chosen. 136 bool success = 137 __atomic_compare_exchange_n(&header_, &expected, newState, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); 138 #endif 139 return success; 140 } 141 SetForwarded()142 inline void SetForwarded() 143 { 144 state_.forwardState_ = ForwardState::FORWARDED; 145 } 146 IsForwarded()147 inline bool IsForwarded() const 148 { 149 return state_.forwardState_ == ForwardState::FORWARDED; 150 } 151 SetLanguageType(LanguageType language)152 inline void SetLanguageType(LanguageType language) 153 { 154 state_.language_ = language; 155 } 156 IsStatic()157 inline bool IsStatic() const 158 { 159 return state_.language_ == LanguageType::STATIC; 160 } 161 IsDynamic()162 inline bool IsDynamic() const 163 { 164 return state_.language_ == LanguageType::DYNAMIC; 165 } 166 167 friend class BaseObject; 168 }; 169 static_assert(sizeof(BaseStateWord) == sizeof(uint64_t), "Excepts 8 bytes"); 170 } // namespace common 171 #endif // COMMON_INTERFACES_OBJECTS_BASE_STATE_WORD_H 172