1 /* 2 * Copyright (c) 2021 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_RUNTIME_INCLUDE_THREAD_H_ 17 #define PANDA_RUNTIME_INCLUDE_THREAD_H_ 18 19 #include <memory> 20 #include <chrono> 21 #include <limits> 22 #include <thread> 23 #include <atomic> 24 25 #include "libpandabase/mem/gc_barrier.h" 26 #include "libpandabase/os/mutex.h" 27 #include "libpandabase/os/thread.h" 28 #include "libpandabase/utils/aligned_storage.h" 29 #include "libpandabase/utils/arch.h" 30 #include "libpandabase/utils/list.h" 31 #include "runtime/include/mem/panda_containers.h" 32 #include "runtime/include/mem/panda_smart_pointers.h" 33 #include "runtime/include/object_header-inl.h" 34 #include "runtime/include/stack_walker.h" 35 #include "runtime/include/language_context.h" 36 #include "runtime/include/locks.h" 37 #include "runtime/include/language_context.h" 38 #include "runtime/include/thread_status.h" 39 #include "runtime/interpreter/cache.h" 40 #include "runtime/interpreter/frame.h" 41 #include "runtime/mem/frame_allocator-inl.h" 42 #include "runtime/mem/gc/gc.h" 43 #include "runtime/mem/internal_allocator.h" 44 #include "runtime/mem/tlab.h" 45 #include "runtime/mem/refstorage/reference_storage.h" 46 #include "runtime/entrypoints/entrypoints.h" 47 #include "events/events.h" 48 49 #define ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS() 50 51 namespace openjdkjvmti { 52 class TiThread; 53 class ScopedNoUserCodeSuspension; 54 } // namespace openjdkjvmti 55 56 namespace panda { 57 58 template <class TYPE> 59 class HandleStorage; 60 template <class TYPE> 61 class GlobalHandleStorage; 62 template <class TYPE> 63 class HandleScope; 64 65 namespace test { 66 class ThreadTest; 67 } // namespace test 68 69 class ThreadManager; 70 class Runtime; 71 class PandaVM; 72 73 namespace mem { 74 class GCBarrierSet; 75 } // namespace mem 76 77 namespace tooling { 78 class PtThreadInfo; 79 } // namespace tooling 80 81 struct CustomTLSData { 82 CustomTLSData() = default; 83 virtual ~CustomTLSData() = default; 84 85 NO_COPY_SEMANTIC(CustomTLSData); 86 NO_MOVE_SEMANTIC(CustomTLSData); 87 }; 88 89 class LockedObjectInfo { 90 public: LockedObjectInfo(ObjectHeader * obj,void * fp)91 LockedObjectInfo(ObjectHeader *obj, void *fp) : object(obj), stack(fp) {} 92 ~LockedObjectInfo() = default; 93 DEFAULT_COPY_SEMANTIC(LockedObjectInfo); 94 DEFAULT_MOVE_SEMANTIC(LockedObjectInfo); GetObject()95 inline ObjectHeader *GetObject() const 96 { 97 return object; 98 } 99 SetObject(ObjectHeader * obj_new)100 inline void SetObject(ObjectHeader *obj_new) 101 { 102 object = obj_new; 103 } 104 GetStack()105 inline void *GetStack() const 106 { 107 return stack; 108 } 109 SetStack(void * stack_new)110 inline void SetStack(void *stack_new) 111 { 112 stack = stack_new; 113 } 114 115 private: 116 ObjectHeader *object; 117 void *stack; 118 }; 119 120 /** 121 * Hierarchy of thread classes 122 * 123 * +--------+ 124 * | Thread | 125 * +--------+ 126 * | 127 * +---------------+ 128 * | ManagedThread | 129 * +---------------+ 130 * | 131 * +-----------------+ 132 * | MTManagedThread | 133 * +-----------------+ 134 * 135 * 136 * Thread - is the most low-level entity. This class contains pointers to VM with which this thread is associated. 137 * ManagedThread - stores runtime context to run managed code in single-threaded environment 138 * MTManagedThread - extends ManagedThread to be able to run code in multi-threaded environment 139 */ 140 141 /** 142 * \brief Class represents arbitrary runtime thread 143 */ 144 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding) 145 class Thread { 146 public: 147 enum class ThreadType { 148 THREAD_TYPE_NONE, 149 THREAD_TYPE_GC, 150 THREAD_TYPE_COMPILER, 151 THREAD_TYPE_MANAGED, 152 THREAD_TYPE_MT_MANAGED, 153 }; 154 Thread(PandaVM * vm,ThreadType thread_type)155 explicit Thread(PandaVM *vm, ThreadType thread_type) : vm_(vm), thread_type_(thread_type) {} 156 virtual ~Thread() = default; 157 NO_COPY_SEMANTIC(Thread); 158 NO_MOVE_SEMANTIC(Thread); 159 160 static Thread *GetCurrent(); 161 static void SetCurrent(Thread *thread); 162 GetVM()163 PandaVM *GetVM() const 164 { 165 return vm_; 166 } 167 SetVM(PandaVM * vm)168 void SetVM(PandaVM *vm) 169 { 170 vm_ = vm; 171 } 172 GetThreadType()173 ThreadType GetThreadType() const 174 { 175 return thread_type_; 176 } 177 178 protected: 179 union __attribute__((__aligned__(4))) FlagsAndThreadStatus { 180 FlagsAndThreadStatus() = default; 181 ~FlagsAndThreadStatus() = default; 182 struct __attribute__((packed)) { 183 volatile uint16_t flags; 184 volatile enum ThreadStatus status; 185 } as_struct; 186 volatile uint32_t as_int; 187 uint32_t as_nonvolatile_int; 188 std::atomic_uint32_t as_atomic; 189 190 NO_COPY_SEMANTIC(FlagsAndThreadStatus); 191 NO_MOVE_SEMANTIC(FlagsAndThreadStatus); 192 }; 193 194 static constexpr size_t STORAGE_32_NUM = 2; 195 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_GLOBAL_VAR_AS_INTERFACE) 196 struct StoragePacked32 : public AlignedStorage<sizeof(uint64_t), sizeof(uint32_t), STORAGE_32_NUM> { 197 Aligned<bool> is_compiled_frame_ {false}; 198 Aligned<union FlagsAndThreadStatus> fts_ {}; 199 } stor_32_; // NOLINT(misc-non-private-member-variables-in-classes) 200 static_assert(sizeof(stor_32_) == StoragePacked32::GetSize()); 201 202 static constexpr size_t STORAGE_PTR_NUM = 9; 203 204 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_GLOBAL_VAR_AS_INTERFACE) 205 struct StoragePackedPtr : public AlignedStorage<sizeof(uintptr_t), sizeof(uintptr_t), STORAGE_PTR_NUM> { 206 Aligned<void *> object_ {nullptr}; 207 Aligned<Frame *> frame_ {nullptr}; 208 Aligned<ObjectHeader *> exception_ {nullptr}; 209 Aligned<uintptr_t> native_pc_ {}; 210 Aligned<mem::TLAB *> tlab_ {nullptr}; 211 Aligned<void *> card_table_addr_ {nullptr}; 212 Aligned<void *> card_table_min_addr_ {nullptr}; 213 Aligned<void *> concurrent_marking_addr_ {nullptr}; 214 Aligned<void *> string_class_ptr_ {nullptr}; 215 } stor_ptr_; // NOLINT(misc-non-private-member-variables-in-classes) 216 static_assert(sizeof(stor_ptr_) == StoragePackedPtr::GetSize()); 217 218 private: 219 PandaVM *vm_ {nullptr}; 220 ThreadType thread_type_ {ThreadType::THREAD_TYPE_NONE}; 221 }; 222 223 template <typename ThreadT> 224 class ScopedCurrentThread { 225 public: ScopedCurrentThread(ThreadT * thread)226 explicit ScopedCurrentThread(ThreadT *thread) : thread_(thread) 227 { 228 ASSERT(Thread::GetCurrent() == nullptr); 229 230 // Set current thread 231 Thread::SetCurrent(thread_); 232 } 233 ~ScopedCurrentThread()234 ~ScopedCurrentThread() 235 { 236 // Reset current thread 237 Thread::SetCurrent(nullptr); 238 } 239 240 NO_COPY_SEMANTIC(ScopedCurrentThread); 241 NO_MOVE_SEMANTIC(ScopedCurrentThread); 242 243 private: 244 ThreadT *thread_; 245 }; 246 247 } // namespace panda 248 249 #endif // PANDA_RUNTIME_INCLUDE_THREAD_H_ 250