1 /** 2 * Copyright (c) 2021-2023 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 PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_SHAREDMEM_H 17 #define PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_SHAREDMEM_H 18 19 #include <atomic> 20 #include <cstdint> 21 #include <optional> 22 #include "include/mem/panda_containers.h" 23 #include "libpandabase/macros.h" 24 #include "libpandabase/mem/space.h" 25 #include "libpandabase/os/mutex.h" 26 #include "libpandabase/mem/object_pointer.h" 27 #include "plugins/ets/runtime/types/ets_class.h" 28 #include "plugins/ets/runtime/types/ets_primitives.h" 29 #include "plugins/ets/runtime/types/ets_object.h" 30 #include "plugins/ets/runtime/ets_class_root.h" 31 #include "plugins/ets/runtime/ets_vm.h" 32 #include "plugins/ets/runtime/types/ets_array.h" 33 34 namespace panda::ets { 35 36 class EtsSharedMemory : public ObjectHeader { 37 public: 38 EtsSharedMemory() = delete; 39 ~EtsSharedMemory() = delete; 40 41 NO_COPY_SEMANTIC(EtsSharedMemory); 42 NO_MOVE_SEMANTIC(EtsSharedMemory); 43 44 class Waiter; 45 AsObject()46 EtsObject *AsObject() 47 { 48 return EtsObject::FromCoreType(this); 49 } 50 AsObject()51 const EtsObject *AsObject() const 52 { 53 return EtsObject::FromCoreType(this); 54 } 55 FromEtsObject(EtsObject * sharedMem)56 static EtsSharedMemory *FromEtsObject(EtsObject *sharedMem) 57 { 58 return reinterpret_cast<EtsSharedMemory *>(sharedMem); 59 } 60 61 static EtsSharedMemory *Create(size_t length); 62 63 void Initialize(size_t length); 64 65 size_t GetLength(); 66 GetHeadWaiter()67 Waiter *GetHeadWaiter() 68 { 69 return reinterpret_cast<Waiter *>(waiter_); 70 } 71 SetHeadWaiter(Waiter * waiter)72 void SetHeadWaiter(Waiter *waiter) 73 { 74 waiter_ = reinterpret_cast<EtsLong>(waiter); 75 } 76 77 void LinkWaiter(Waiter &waiter); 78 void UnlinkWaiter(Waiter &waiter); 79 80 int8_t GetElement(uint32_t index); 81 void SetElement(uint32_t index, int8_t element); 82 83 template <typename F> 84 std::pair<int8_t, int8_t> ReadModifyWriteI8(int32_t index, const F &f); 85 86 enum class WaitResult { OK = 0, NOT_EQUAL = 1, TIMED_OUT = 2 }; 87 88 WaitResult WaitI32(uint32_t offset, int32_t expectedValue, std::optional<uint64_t> timeout); 89 90 WaitResult WaitI64(uint32_t offset, int64_t expectedValue, std::optional<uint64_t> timeout); 91 92 int32_t NotifyI32(uint32_t offset, std::optional<uint32_t> count); 93 94 class Waiter { 95 public: Waiter(uint32_t offset)96 explicit Waiter(uint32_t offset) : offset_(offset) {} 97 98 bool Wait(std::optional<uint64_t> timeout); 99 100 void SignalAll(); 101 IsNotified()102 bool IsNotified() 103 { 104 // Atomic with seq_cst order reason: strong synchronization 105 return notified_.load(std::memory_order_seq_cst); 106 } 107 SetNotified()108 void SetNotified() 109 { 110 // Atomic with seq_cst order reason: strong synchronization 111 notified_.store(true, std::memory_order_seq_cst); 112 } 113 GetOffset()114 uint32_t GetOffset() 115 { 116 return offset_; 117 } 118 GetNext()119 Waiter *GetNext() 120 { 121 return next_; 122 } 123 SetNext(Waiter * next)124 void SetNext(Waiter *next) 125 { 126 next_ = next; 127 } 128 GetPrev()129 Waiter *GetPrev() 130 { 131 return prev_; 132 } 133 SetPrev(Waiter * prev)134 void SetPrev(Waiter *prev) 135 { 136 prev_ = prev; 137 } 138 139 private: 140 os::memory::ConditionVariable cv_ {os::memory::ConditionVariable()}; 141 std::atomic<bool> notified_ {std::atomic<bool>(false)}; 142 uint32_t offset_; 143 144 Waiter *prev_ {nullptr}; 145 Waiter *next_ {nullptr}; 146 }; 147 148 private: 149 ObjectPointer<EtsByteArray> array_; 150 EtsLong waiter_; 151 }; 152 153 } // namespace panda::ets 154 155 #endif // PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_SHAREDMEM_H 156