namespace mirror { class Array; classClass; class ClassLoader; class Object; template<class T> class ObjectArray; template<class T> class PrimitiveArray; using IntArray = PrimitiveArray<int32_t>; class StackTraceElement; class String; class Throwable;
} // namespace mirror
namespace verifier { class VerifierDeps;
} // namespace verifier
class ArtMethod; class BaseMutex; class ClassLinker; class Closure; class Context; class DeoptimizationContextRecord; class DexFile; class FrameIdToShadowFrame; class IsMarkedVisitor; class JavaVMExt; class JNIEnvExt; class Monitor; class RootVisitor; class ScopedObjectAccessAlreadyRunnable; class ShadowFrame; class StackedShadowFrameRecord; class Thread; class ThreadList; enum VisitRootFlags : uint8_t; enumclass LowOverheadTraceType;
// A piece of data that can be held in the CustomTls. The destructor will be called during thread // shutdown. The thread the destructor is called on is not necessarily the same thread it was stored // on. class TLSData { public: virtual ~TLSData() {}
};
// Thread priorities. These must match the Thread.MIN_PRIORITY, // Thread.NORM_PRIORITY, and Thread.MAX_PRIORITY constants. enum ThreadPriority {
kMinThreadPriority = 1,
kNormThreadPriority = 5,
kMaxThreadPriority = 10,
};
enumclass ThreadFlag : uint32_t { // If set, implies that suspend_count_ > 0 and the Thread should enter the safepoint handler.
kSuspendRequest = 1u << 0,
// Request that the thread do some checkpoint work and then continue. // Only modified while holding thread_suspend_count_lock_ .
kCheckpointRequest = 1u << 1,
// Request that the thread do empty checkpoint and then continue.
kEmptyCheckpointRequest = 1u << 2,
// Register that at least 1 suspend barrier needs to be passed. // Changes to this flag are guarded by suspend_count_lock_ .
kActiveSuspendBarrier = 1u << 3,
// Marks that a "flip function" needs to be executed on this thread. // Set only while holding thread_list_lock_.
kPendingFlipFunction = 1u << 4,
// Marks that the "flip function" is being executed by another thread. // // This is used to guard against multiple threads trying to run the // "flip function" for the same thread while the thread is suspended. // // Set when we have some way to ensure that the thread cannot disappear out from under us, // Either: // 1) Set by the thread itself, // 2) by a thread holding thread_list_lock_, or // 3) while the target has a pending suspension request. // Once set, prevents a thread from exiting.
kRunningFlipFunction = 1u << 5,
// We are responsible for resuming all other threads. We ignore suspension requests, // but not checkpoint requests, until a more opportune time. GC code should // in any case not check for such requests; other clients of SuspendAll might. // Prevents a situation in which we are asked to suspend just before we suspend all // other threads, and then notice the suspension request and suspend ourselves, // leading to deadlock. Guarded by thread_suspend_count_lock_ . // Should not ever be set when we try to transition to kRunnable. // TODO(b/296639267): Generalize use to prevent SuspendAll from blocking // in-progress GC.
kSuspensionImmune = 1u << 6,
// Request that compiled JNI stubs do not transition to Native or Runnable with // inlined code, but take a slow path for monitoring method entry and exit events.
kMonitorJniEntryExit = 1u << 7,
// Indicates the last flag. Used for checking that the flags do not overlap thread state.
kLastFlag = kMonitorJniEntryExit
};
// The type of method that triggers deoptimization. It contains info on whether // the deoptimized method should advance dex_pc. enumclass DeoptimizationMethodType {
kKeepDexPc, // dex pc is required to be kept upon deoptimization.
kDefault // dex pc may or may not advance depending on other conditions.
};
// For the CC colector, normal weak reference access can be disabled on a per-thread basis, while // processing references. After finishing, the reference processor asynchronously sets the // per-thread flags back to kEnabled with release memory ordering semantics. Each mutator thread // should check its flag with acquire semantics before assuming that it is enabled. However, // that is often too expensive, so the reading thread sets it to kVisiblyEnabled after seeing it // kEnabled. The Reference.get() intrinsic can thus read it in relaxed mode, and reread (by // resorting to the slow path) with acquire semantics if it sees a value of kEnabled rather than // kVisiblyEnabled. enumclass WeakRefAccessState : int32_t {
kVisiblyEnabled = 0, // Enabled, and previously read with acquire load by this thread.
kEnabled,
kDisabled
};
enum VirtualThreadFlag : uint8_t { // This flag is set only when carrier thread enters a jdk.internal.vm.Continuation. // In this case, the Continuation is the internal implementation details of virtual thread. // Importantly, virtual thread frames are on top of the carrier thread frames.
kContinuation = 1u, // The flag is set when a virtual thread is being parked and unmounted from the carrier thread.
kParking = 1u << 1, // The flag is set when a virtual thread is being unparked and mounted from the carrier thread.
kUnparking = 1u << 2,
};
// ART uses two types of ABI/code: quick and native. // // Quick code includes: // - The code that ART compiles to, e.g: Java/dex code compiled to Arm64. // - Quick assembly entrypoints. // // Native code includes: // - Interpreter. // - GC. // - JNI. // - Runtime methods, i.e.: all ART C++ code. // // In regular (non-simulator) mode, both native and quick code are of the same ISA and will operate // on the hardware stack. The hardware stack is allocated by the kernel to ART and grows down in // memory. // // In simulator mode, native and quick code use different ISA's and will use different stacks. // Native code will use the hardware stack while quick code will use the simulated stack. The // simulated stack is a simple buffer in the native heap owned by the Simulator class. // // The StackType enum reflects the underlying type of stack in use by any given function while two // constexpr StackTypes (kNativeStackType and kQuickStackType) indicate which type of stack is used // for native and quick code. Whenever possible kNativeStackType and kQuickStackType should be used // instead of using the StackType directly. enumclass StackType {
kHardware,
kSimulated
};
// The type of stack used when executing native code, i.e.: runtime helpers, interpreter, JNI, etc. // This stack is the native machine's call stack and so should be used when comparing against // values returned from builtin functions such as __builtin_frame_address. static constexpr StackType kNativeStackType = StackType::kHardware;
// The type of stack used when executing quick code, i.e.: compiled dex code and quick entrypoints. // For simulator builds this is the kSimulated stack and for non-simulator builds this is the // kHardware stack. #ifdef ART_USE_SIMULATOR static constexpr StackType kQuickStackType = StackType::kSimulated; #else static constexpr StackType kQuickStackType = StackType::kHardware; #endif
// See Thread.tlsPtr_.active_suspend1_barriers below for explanation. struct WrappedSuspend1Barrier { // TODO(b/323668816): At least weaken CHECKs to DCHECKs once the bug is fixed. static constexpr int kMagic = 0xba8;
WrappedSuspend1Barrier() : magic_(kMagic), barrier_(1), next_(nullptr) {} int magic_;
AtomicInteger barrier_; struct WrappedSuspend1Barrier* next_ GUARDED_BY(Locks::thread_suspend_count_lock_);
};
// Mostly opaque structure allocated by the client of NotifyOnThreadExit. Allows a client to // check whether the thread still exists after temporarily releasing thread_list_lock_, usually // because we need to wait for something. class ThreadExitFlag { public:
ThreadExitFlag() : exited_(false) {} bool HasExited() REQUIRES(Locks::thread_list_lock_) { return exited_; }
private: // All ThreadExitFlags associated with a thread and with exited_ == false are in a doubly linked // list. tlsPtr_.thread_exit_flags points to the first element. first.prev_ and last.next_ are // null. This list contains no ThreadExitFlags with exited_ == true;
ThreadExitFlag* next_ GUARDED_BY(Locks::thread_list_lock_);
ThreadExitFlag* prev_ GUARDED_BY(Locks::thread_list_lock_); bool exited_ GUARDED_BY(Locks::thread_list_lock_); friendclass Thread;
};
// The data values should only be accessed by the carrier thread itself, except // the next_ pointer. struct MountedVirtualThreadData {
MountedVirtualThreadData(uint32_t virtual_thread_id, uint32_t carrier_thread_id, uint8_t flags)
: virtual_thread_id_(virtual_thread_id),
carrier_thread_id_(carrier_thread_id),
flags_(flags),
next_(nullptr) {} const uint32_t virtual_thread_id_; const uint32_t carrier_thread_id_;
uint8_t flags_; // art::ThreadList stores a linked list of mounted virtual threads in this field.
MountedVirtualThreadData* next_ GUARDED_BY(Locks::thread_list_lock_);
};
// Thread's stack layout for implicit stack overflow checks: // // +---------------------+ <- highest address of stack memory // | | // . . <- SP // | | // | | // +---------------------+ <- stack_end // | | // | Gap | // | | // +---------------------+ <- stack_begin // | | // | Protected region | // | | // +---------------------+ <- lowest address of stack memory // // The stack always grows down in memory. At the lowest address is a region of memory // that is set mprotect(PROT_NONE). Any attempt to read/write to this region will // result in a segmentation fault signal. At any point, the thread's SP will be somewhere // between the stack_end and the highest address in stack memory. An implicit stack // overflow check is a read of memory at a certain offset below the current SP (8K typically). // If the thread's SP is below the stack_end address this will be a read into the protected // region. If the SP is above the stack_end address, the thread is guaranteed to have // at least 8K of space. Because stack overflow checks are only performed in generated code, // if the thread makes a call out to a native function (through JNI), that native function // might only have 4K of memory (if the SP is adjacent to stack_end). class EXPORT Thread { public: staticconst size_t kStackOverflowImplicitCheckSize; static constexpr bool kVerifyStack = kIsDebugBuild;
// Creates a new native thread corresponding to the given managed peer. // Used to implement Thread.start. staticvoid CreateNativeThread(JNIEnv* env, jobject peer, size_t stack_size, bool daemon);
// Attaches the calling native thread to the runtime, returning the new native peer. // Used to implement JNI AttachCurrentThread and AttachCurrentThreadAsDaemon calls. static Thread* Attach(constchar* thread_name, bool as_daemon,
jobject thread_group, bool create_peer, bool should_run_callbacks); // Attaches the calling native thread to the runtime, returning the new native peer. static Thread* Attach(constchar* thread_name, bool as_daemon, jobject thread_peer);
// Reset internal state of child thread after fork. void InitAfterFork();
// Get the currently executing thread, frequently referred to as 'self'. This call has reasonably // high cost and so we favor passing self around when possible. // TODO: mark as PURE so the compiler may coalesce and remove? static Thread* Current();
// Get the thread from the JNI environment. static Thread* ForEnv(JNIEnv* env);
// For implicit overflow checks we reserve an extra piece of memory at the bottom of the stack // (lowest memory). The higher portion of the memory is protected against reads and the lower is // available for use while throwing the StackOverflow exception.
ALWAYS_INLINE static size_t GetStackOverflowProtectedSize();
// On a runnable thread, check for pending thread suspension request and handle if pending. void AllowThreadSuspension() REQUIRES_SHARED(Locks::mutator_lock_);
// Process pending thread suspension request and handle if pending. void CheckSuspend(bool implicit = false) REQUIRES_SHARED(Locks::mutator_lock_);
// Process a pending empty checkpoint if pending. void CheckEmptyCheckpointFromWeakRefAccess(BaseMutex* cond_var_mutex); void CheckEmptyCheckpointFromMutex();
// Translates 172 to pAllocArrayFromCode and so on. template<PointerSize size_of_pointers> staticvoid DumpThreadOffset(std::ostream& os, uint32_t offset);
// Dumps a one-line summary of thread state (used for operator<<). void ShortDump(std::ostream& os) const;
// Order of threads for ANRs (ANRs can be trimmed, so we print important ones first). enumclass DumpOrder : uint8_t {
kMain, // Always print the main thread first (there might not be one).
kBlocked, // Then print all threads that are blocked due to waiting on lock.
kLocked, // Then print all threads that are holding some lock already.
kDefault, // Print all other threads which might not be interesting for ANR.
};
// Dumps the detailed thread state and the thread stack (used for SIGQUIT).
DumpOrder Dump(std::ostream& os, bool dump_native_stack = true, bool force_dump_stack = false) const
REQUIRES_SHARED(Locks::mutator_lock_);
DumpOrder Dump(std::ostream& os,
unwindstack::AndroidLocalUnwinder& unwinder, bool dump_native_stack = true, bool force_dump_stack = false) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Dumps the SIGQUIT per-thread header. 'thread' can be null for a non-attached thread, in which // case we use 'tid' to identify the thread, and we'll include as much information as we can. staticvoid DumpState(std::ostream& os, const Thread* thread, pid_t tid)
REQUIRES_SHARED(Locks::mutator_lock_);
int GetSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_) { return tls32_.suspend_count;
}
int GetUserCodeSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_,
Locks::user_code_suspension_lock_) { return tls32_.user_code_suspend_count;
}
bool IsSuspended() const { // We need to ensure that once we return true, all prior accesses to the Java data by "this" // thread are complete. Hence we need "acquire" ordering here, and "release" when the flags // are set.
StateAndFlags state_and_flags = GetStateAndFlags(std::memory_order_acquire); return state_and_flags.GetState() != ThreadState::kRunnable &&
state_and_flags.IsFlagSet(ThreadFlag::kSuspendRequest);
}
// Increment suspend count and optionally install at most one suspend barrier. // Must hold thread_list_lock, OR be called with self == this, so that the Thread cannot // disappear while we're running. If it's known that this == self, and thread_list_lock_ // is not held, FakeMutexLock should be used to fake-acquire thread_list_lock_ for // static checking purposes.
ALWAYS_INLINE void IncrementSuspendCount(Thread* self,
AtomicInteger* suspendall_barrier,
WrappedSuspend1Barrier* suspend1_barrier,
SuspendReason reason) REQUIRES(Locks::thread_suspend_count_lock_)
REQUIRES(Locks::thread_list_lock_);
// The same, but default reason to kInternal, and barriers to nullptr.
ALWAYS_INLINE void IncrementSuspendCount(Thread* self) REQUIRES(Locks::thread_suspend_count_lock_)
REQUIRES(Locks::thread_list_lock_);
// Follows one of the above calls. For_user_code indicates if SuspendReason was kForUserCode. // Generally will need to be closely followed by Thread::resume_cond_->Broadcast(self); // since there may be waiters. DecrementSuspendCount() itself does not do this, since we often // wake more than a single thread.
ALWAYS_INLINE void DecrementSuspendCount(Thread* self, bool for_user_code = false)
REQUIRES(Locks::thread_suspend_count_lock_);
public: // Requests a checkpoint closure to run on another thread. The closure will be run when the // thread notices the request, either in an explicit runtime CheckSuspend() call, or in a call // originating from a compiler generated suspend point check. This returns true if the closure // was added and will (eventually) be executed. It returns false if this was impossible // because the thread was suspended, and we thus did nothing. // // Since multiple closures can be queued and some closures can delay other threads from running, // no closure should attempt to suspend another thread while running. // TODO We should add some debug option that verifies this. // // This guarantees that the RequestCheckpoint invocation happens-before the function invocation: // RequestCheckpointFunction holds thread_suspend_count_lock_, and RunCheckpointFunction // acquires it. bool RequestCheckpoint(Closure* function)
REQUIRES(Locks::thread_suspend_count_lock_);
// RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. This is // due to the fact that Thread::Current() needs to go to sleep to allow the targeted thread to // execute the checkpoint for us if it is Runnable. The wait_state is the state that the thread // will go into while it is awaiting the checkpoint to be run. // The closure may be run on Thread::Current() on behalf of "this" thread. // Thus for lock ordering purposes, the closure should be runnable by the caller. This also // sometimes makes it reasonable to pass ThreadState::kRunnable as wait_state: We may wait on // a condition variable for the "this" thread to act, but for lock ordering purposes, this is // exactly as though Thread::Current() had run the closure. // NB Since multiple closures can be queued and some closures can delay other threads from running // no closure should attempt to suspend another thread while running. bool RequestSynchronousCheckpoint(Closure* function,
ThreadState wait_state = ThreadState::kWaiting)
REQUIRES_SHARED(Locks::mutator_lock_) RELEASE(Locks::thread_list_lock_)
REQUIRES(!Locks::thread_suspend_count_lock_);
// Set the flip function. This is done with all threads suspended, except for the calling thread. void SetFlipFunction(Closure* function) REQUIRES(Locks::thread_suspend_count_lock_)
REQUIRES(Locks::thread_list_lock_);
// Wait for the flip function to complete if still running on another thread. Assumes the "this" // thread remains live. void WaitForFlipFunction(Thread* self) const REQUIRES(!Locks::thread_suspend_count_lock_);
// An enhanced version of the above that uses tef to safely return if the thread exited in the // meantime. void WaitForFlipFunctionTestingExited(Thread* self, ThreadExitFlag* tef)
REQUIRES(!Locks::thread_suspend_count_lock_, !Locks::thread_list_lock_);
// Called when thread detected that the thread_suspend_count_ was non-zero. Gives up share of // mutator_lock_ and waits until it is resumed and thread_suspend_count_ is zero. // Should be called only when the kSuspensionImmune flag is clear. Requires this == Current(); void FullSuspendCheck(bool implicit = false)
REQUIRES(!Locks::thread_suspend_count_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
// Transition from non-runnable to runnable state acquiring share on mutator_lock_. Returns the // old state, or kInvalidState if we failed because allow_failure and kSuspensionImmune were set. // Should not be called with an argument except by the next function below.
ALWAYS_INLINE ThreadState TransitionFromSuspendedToRunnable(bool fail_on_suspend_req = false)
REQUIRES(!Locks::thread_suspend_count_lock_) SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
// A version that does not return the old ThreadState, and fails by returning false if it would // have needed to handle a pending suspension request.
ALWAYS_INLINE bool TryTransitionFromSuspendedToRunnable()
REQUIRES(!Locks::thread_suspend_count_lock_)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS { // The above function does not really acquire the lock when we pass true and it returns // kInvalidState. We lie in both places, but clients see correct behavior. return TransitionFromSuspendedToRunnable(true) != ThreadState::kInvalidState;
}
// Transition from runnable into a state where mutator privileges are denied. Releases share of // mutator lock.
ALWAYS_INLINE void TransitionFromRunnableToSuspended(ThreadState new_state)
REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
UNLOCK_FUNCTION(Locks::mutator_lock_);
// Once called thread suspension will cause an assertion failure. constchar* StartAssertNoThreadSuspension(constchar* cause) ACQUIRE(Roles::uninterruptible_) {
Roles::uninterruptible_.Acquire(); // No-op. if (kIsDebugBuild) {
CHECK(cause != nullptr); constchar* previous_cause = tlsPtr_.last_no_thread_suspension_cause;
tls32_.no_thread_suspension++;
tlsPtr_.last_no_thread_suspension_cause = cause; return previous_cause;
} else { return nullptr;
}
}
// End region where no thread suspension is expected. void EndAssertNoThreadSuspension(constchar* old_cause) RELEASE(Roles::uninterruptible_) { if (kIsDebugBuild) {
CHECK_IMPLIES(old_cause == nullptr, tls32_.no_thread_suspension == 1);
CHECK_GT(tls32_.no_thread_suspension, 0U);
tls32_.no_thread_suspension--;
tlsPtr_.last_no_thread_suspension_cause = old_cause;
}
Roles::uninterruptible_.Release(); // No-op.
}
// End region where no thread suspension is expected. Returns the current open region in case we // want to reopen it. Used for ScopedAllowThreadSuspension. Not supported if no_thread_suspension // is larger than one. constchar* EndAssertNoThreadSuspension() RELEASE(Roles::uninterruptible_) WARN_UNUSED { constchar* ret = nullptr; if (kIsDebugBuild) {
CHECK_EQ(tls32_.no_thread_suspension, 1u);
tls32_.no_thread_suspension--;
ret = tlsPtr_.last_no_thread_suspension_cause;
tlsPtr_.last_no_thread_suspension_cause = nullptr;
}
Roles::uninterruptible_.Release(); // No-op. return ret;
}
// Return true if thread suspension is allowable. bool IsThreadSuspensionAllowable() const;
bool IsDaemon() const { return tls32_.daemon;
}
size_t NumberOfHeldMutexes() const;
// Does the current thread hold the monitor for `object`? Assumes this == Thread::Current(). bool HoldsLock(ObjPtr<mirror::Object> object) const REQUIRES_SHARED(Locks::mutator_lock_);
/* *ReturnPosixnicenessinsteadofJavapriority.Averythinwrapperovergetpriority().May *beinconsistentwithPaletteSchedSetPriority,especiallyifthatdoesn'tactuallyadjust *priorities.
*/ int GetNativeNiceness() const;
/* *Returnthenicenessvalueforthisthread,ascachedbytheJavalayer,orzeroifthereis *noJavapeer.Assumesself==this.
*/ int GetCachedNiceness() const REQUIRES_SHARED(Locks::mutator_lock_);
// Guaranteed to be non-zero.
uint32_t GetThreadId() const { return tls32_.thin_lock_thread_id;
}
// Returns the thread id used for java monitor lock purpose. If a virtual thread is mounted on // this platform thread, the thread id of the virtual thread is returned.
ALWAYS_INLINE uint32_t GetMonitorThreadId() const {
DCHECK_EQ(this, Thread::Current())
<< "GetMonitorThreadId() should only be called on the current thread."; return IsVirtualThreadMounted() ? GetVirtualThreadId() : GetThreadId();
}
pid_t GetTid() const { return tls32_.tid;
}
// Returns the java.lang.Thread's name, or null if this Thread* doesn't have a peer.
ObjPtr<mirror::String> GetThreadName() const REQUIRES_SHARED(Locks::mutator_lock_);
// Sets 'name' to the java.lang.Thread's name. This requires no transition to managed code, // allocation, or locking. void GetThreadName(std::string& name) const;
// Sets the thread's name. void SetThreadName(constchar* name) REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the thread-specific CPU-time clock in microseconds or -1 if unavailable.
uint64_t GetCpuMicroTime() const;
// Returns the thread-specific CPU-time clock in nanoseconds or -1 if unavailable.
uint64_t GetCpuNanoTime() const;
mirror::Object* GetPeer() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(Thread::Current() == this) << "Use GetPeerFromOtherThread instead";
CHECK(tlsPtr_.jpeer == nullptr); return tlsPtr_.opeer;
} // GetPeer is not safe if called on another thread in the middle of the thread flip and // the thread's stack may have not been flipped yet and peer may be a from-space (stale) ref. // This function will force a flip for the other thread if necessary. // Since we hold a shared mutator lock, a new flip function cannot be concurrently installed. // The target thread must be suspended, so that it cannot disappear during the call. // We should ideally not hold thread_list_lock_ . GetReferenceKind in ti_heap.cc, currently does // hold it, but in a context in which we do not invoke EnsureFlipFunctionStarted().
mirror::Object* GetPeerFromOtherThread() REQUIRES_SHARED(Locks::mutator_lock_);
// A version of the above that requires thread_list_lock_, but does not require the thread to // be suspended. This may temporarily release thread_list_lock_. It thus needs a ThreadExitFlag // describing the thread's status, so we can tell if it exited in the interim. Returns null if // the thread exited.
mirror::Object* LockedGetPeerFromOtherThread(ThreadExitFlag* tef)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::thread_list_lock_);
// A convenience version of the above that creates the ThreadExitFlag locally. This is often // unsafe if more than one thread is being processed. A prior call may have released // thread_list_lock_, and thus the NotifyOnThreadExit() call here could see a deallocated // Thread. We must hold the thread_list_lock continuously between obtaining the Thread* // and calling NotifyOnThreadExit().
mirror::Object* LockedGetPeerFromOtherThread() REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(Locks::thread_list_lock_) {
ThreadExitFlag tef;
NotifyOnThreadExit(&tef);
mirror::Object* result = LockedGetPeerFromOtherThread(&tef);
UnregisterThreadExitFlag(&tef); return result;
}
// Set the current Thread object returned by Thread.currentThread(). void SetCurrentPeer(mirror::Object* peer) REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(Thread::Current() == this) << "Don't call this from another thread.";
tlsPtr_.current_peer = peer;
}
// Get the current Thread object returned by Thread.currentThread().
mirror::Object* GetCurrentPeer() REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(Thread::Current() == this) << "Don't call this from another thread."; return tlsPtr_.current_peer;
}
// Set an exception that is asynchronously thrown from a different thread. This will be checked // periodically and might overwrite the current 'Exception'. This can only be called from a // checkpoint. // // The caller should also make sure that the thread has been deoptimized so that the exception // could be detected on back-edges. void SetAsyncException(ObjPtr<mirror::Throwable> new_exception)
REQUIRES_SHARED(Locks::mutator_lock_);
// Move the current async-exception to the main exception. This should be called when the current // thread is ready to deal with any async exceptions. Returns true if there is an async exception // that needs to be dealt with, false otherwise. bool ObserveAsyncException() REQUIRES_SHARED(Locks::mutator_lock_);
// Find catch block then prepare and return the long jump context to the appropriate exception // handler. When is_method_exit_exception is true, the exception was thrown by the method exit // callback and we should not send method unwind for the method on top of the stack since method // exit callback was already called.
std::unique_ptr<Context> QuickDeliverException(bool is_method_exit_exception = false)
REQUIRES_SHARED(Locks::mutator_lock_);
// Perform deoptimization. Return a `Context` prepared for a long jump.
std::unique_ptr<Context> Deoptimize(DeoptimizationKind kind, bool single_frame, bool skip_method_exit_callbacks)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get the current method and dex pc. If there are errors in retrieving the dex pc, this will // abort the runtime iff abort_on_error is true.
ArtMethod* GetCurrentMethod(uint32_t* dex_pc, bool check_suspended = true, bool abort_on_error = true) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns whether the given exception was thrown by the current Java method being executed // (Note that this includes native Java methods). bool IsExceptionThrownByCurrentMethod(ObjPtr<mirror::Throwable> exception) const
REQUIRES_SHARED(Locks::mutator_lock_);
// If 'msg' is null, no detail message is set. void ThrowNewException(constchar* exception_class_descriptor, constchar* msg)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// If 'msg' is null, no detail message is set. An exception must be pending, and will be // used as the new exception's cause. void ThrowNewWrappedException(constchar* exception_class_descriptor, constchar* msg)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// OutOfMemoryError is special, because we need to pre-allocate an instance. // Only the GC should call this. void ThrowOutOfMemoryError(constchar* msg) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
// Notify this thread's thread-group that this thread has started. // Note: the given thread-group is used as a fast path and verified in debug build. If the value // is null, the thread's thread-group is loaded from the peer. void NotifyThreadGroup(ScopedObjectAccessAlreadyRunnable& soa, jobject thread_group = nullptr)
REQUIRES_SHARED(Locks::mutator_lock_);
// Request notification when this thread is unregistered, typically because it has exited. // // The ThreadExitFlag status is only changed when we remove the thread from the thread list, // which we only do once no suspend requests are outstanding, and no flip-functions are still // running. // // The caller must allocate a fresh ThreadExitFlag, and pass it in. The caller is responsible // for either waiting until the thread has exited, or unregistering the ThreadExitFlag, and // then, and only then, deallocating the ThreadExitFlag. (This scheme avoids an allocation and // questions about what to do if the allocation fails. Allows detection of thread exit after // temporary release of thread_list_lock_) void NotifyOnThreadExit(ThreadExitFlag* tef) REQUIRES(Locks::thread_list_lock_); void UnregisterThreadExitFlag(ThreadExitFlag* tef) REQUIRES(Locks::thread_list_lock_);
// Is the ThreadExitFlag currently registered in this thread, which has not yet terminated? // Intended only for testing. bool IsRegistered(ThreadExitFlag* query_tef) REQUIRES(Locks::thread_list_lock_);
// For debuggable builds, CHECK that neither first nor last, nor any ThreadExitFlag with an // address in-between, is currently registered with any thread. staticvoid DCheckUnregisteredEverywhere(ThreadExitFlag* first, ThreadExitFlag* last)
REQUIRES(!Locks::thread_list_lock_);
// Called when thread is unregistered. May be called repeatedly, in which case only newly // registered clients are processed. void SignalExitFlags() REQUIRES(Locks::thread_list_lock_);
// Convert a jobject into a Object*
ObjPtr<mirror::Object> DecodeJObject(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_); // Checks if the weak global ref has been cleared by the GC without decoding it. bool IsJWeakCleared(jweak obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Parking for 0ns of relative time means an untimed park, negative (though // should be handled in java code) returns immediately void Park(bool is_absolute, int64_t time) REQUIRES_SHARED(Locks::mutator_lock_); void Unpark();
// Returns true when a virtual thread is mounted on this platform thread.
ALWAYS_INLINE bool IsVirtualThreadMounted() const {
MountedVirtualThreadData* data = GetMountedVirtualThreadData();
DCHECK(kIsVirtualThreadEnabled || data == nullptr); return kIsVirtualThreadEnabled && data != nullptr;
}
// Callers should check IsVirtualThreadMounted() before calling GetVirtualThreadId().
ALWAYS_INLINE uint32_t GetVirtualThreadId() const {
DCHECK(IsVirtualThreadMounted());
DCHECK_EQ(this, Thread::Current())
<< "GetVirtualThreadId() should only be called on the current thread.";
MountedVirtualThreadData* data = GetMountedVirtualThreadData(); return data->virtual_thread_id_;
}
// Create the internal representation of a stack trace, that is more time // and space efficient to compute than the StackTraceElement[].
ObjPtr<mirror::ObjectArray<mirror::Object>> CreateInternalStackTrace( const ScopedObjectAccessAlreadyRunnable& soa) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Convert an internal stack trace representation (returned by CreateInternalStackTrace) to a // StackTraceElement[]. If output_array is null, a new array is created, otherwise as many // frames as will fit are written into the given array. If stack_depth is non-null, it's updated // with the number of valid frames in the returned array. static jobjectArray InternalStackTraceToStackTraceElementArray( const ScopedObjectAccessAlreadyRunnable& soa, jobject internal,
jobjectArray output_array = nullptr, int* stack_depth = nullptr)
REQUIRES_SHARED(Locks::mutator_lock_);
static jint InternalStackTraceToStackFrameInfoArray( const ScopedObjectAccessAlreadyRunnable& soa,
jlong mode, // See java.lang.StackStreamFactory for the mode flags
jobject internal,
jint startLevel,
jint batchSize,
jint startIndex,
jobjectArray output_array) // java.lang.StackFrameInfo[]
REQUIRES_SHARED(Locks::mutator_lock_);
// Check that the thread state is valid. Try to fail if the thread has erroneously terminated. // Note that once the thread has been terminated, it can also be deallocated. But even if the // thread state has been overwritten, the value is unlikely to be in the correct range. void VerifyState() { if (kIsDebugBuild) {
ThreadState state = GetState();
StateAndFlags::ValidateThreadState(state);
DCHECK_NE(state, ThreadState::kTerminated);
}
}
void VerifyStack() REQUIRES_SHARED(Locks::mutator_lock_) { if (kVerifyStack) {
VerifyStackImpl();
}
}
// // Offsets of various members of native Thread class, used by compiled code. //
// Return the entry point offset integer value for ReadBarrierMarkRegX, where X is `reg`. template <PointerSize pointer_size> static constexpr int32_t ReadBarrierMarkEntryPointsOffset(size_t reg) { // The entry point list defines 30 ReadBarrierMarkRegX entry points.
DCHECK_LT(reg, 30u); // The ReadBarrierMarkRegX entry points are ordered by increasing // register number in Thread::tls_Ptr_.quick_entrypoints. return QUICK_ENTRYPOINT_OFFSET(pointer_size, pReadBarrierMarkReg00).Int32Value()
+ static_cast<size_t>(pointer_size) * reg;
}
// Set the stack end to that to be used during a stack overflow template <StackType stack_type>
ALWAYS_INLINE void SetStackEndForStackOverflow()
REQUIRES_SHARED(Locks::mutator_lock_);
// Set the stack end to that to be used during regular execution template <StackType stack_type>
ALWAYS_INLINE void ResetDefaultStackEnd();
// Is the given object on the quick stack? bool IsRawObjOnQuickStack(uint8_t* raw_obj) const;
// Is the given obj in one of this thread's JNI transition frames? bool IsJniTransitionReference(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
// Convert a global (or weak global) jobject into a Object*
ObjPtr<mirror::Object> DecodeGlobalJObject(jobject obj) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if the thread is allowed to load java classes. bool CanLoadClasses() const;
// Returns the fake exception used to activate deoptimization. static mirror::Throwable* GetDeoptimizationException() { // Note that the mirror::Throwable must be aligned to kObjectAlignment or else it cannot be // represented by ObjPtr. returnreinterpret_cast<mirror::Throwable*>(0x100);
}
// Currently deoptimization invokes verifier which can trigger class loading // and execute Java code, so there might be nested deoptimizations happening. // We need to save the ongoing deoptimization shadow frames and return // values on stacks. // 'from_code' denotes whether the deoptimization was explicitly made from // compiled code. // 'method_type' contains info on whether deoptimization should advance // dex_pc. void PushDeoptimizationContext(const JValue& return_value, bool is_reference,
ObjPtr<mirror::Throwable> exception, bool from_code,
DeoptimizationMethodType method_type)
REQUIRES_SHARED(Locks::mutator_lock_); void PopDeoptimizationContext(JValue* result,
ObjPtr<mirror::Throwable>* exception, bool* from_code,
DeoptimizationMethodType* method_type)
REQUIRES_SHARED(Locks::mutator_lock_); void AssertHasDeoptimizationContext()
REQUIRES_SHARED(Locks::mutator_lock_); void PushStackedShadowFrame(ShadowFrame* sf, StackedShadowFrameType type);
ShadowFrame* PopStackedShadowFrame();
ShadowFrame* MaybePopDeoptimizedStackedShadowFrame();
// For debugger, find the shadow frame that corresponds to a frame id. // Or return null if there is none.
ShadowFrame* FindDebuggerShadowFrame(size_t frame_id)
REQUIRES_SHARED(Locks::mutator_lock_); // For debugger, find the bool array that keeps track of the updated vreg set // for a frame id. bool* GetUpdatedVRegFlags(size_t frame_id) REQUIRES_SHARED(Locks::mutator_lock_); // For debugger, find the shadow frame that corresponds to a frame id. If // one doesn't exist yet, create one and track it in frame_id_to_shadow_frame.
ShadowFrame* FindOrCreateDebuggerShadowFrame(size_t frame_id,
uint32_t num_vregs,
ArtMethod* method,
uint32_t dex_pc)
REQUIRES_SHARED(Locks::mutator_lock_);
// Delete the entry that maps from frame_id to shadow_frame. void RemoveDebuggerShadowFrameMapping(size_t frame_id)
REQUIRES_SHARED(Locks::mutator_lock_);
// It is the responsability of the caller to make sure the verifier_deps // entry in the thread is cleared before destruction of the actual VerifierDeps // object, or the thread. void SetVerifierDeps(verifier::VerifierDeps* verifier_deps) {
DCHECK(IsAotCompiler());
DCHECK(verifier_deps == nullptr || tlsPtr_.deps_or_stack_trace_sample.verifier_deps == nullptr);
tlsPtr_.deps_or_stack_trace_sample.verifier_deps = verifier_deps;
}
// Possibly check that no mutexes at level kMonitorLock or above are subsequently acquired. // Only invoked by the thread itself. void DisallowPreMonitorMutexes();
// Undo the effect of the previous call. Again only invoked by the thread itself. void AllowPreMonitorMutexes();
// Read a flag with the given memory order. See mutator_gc_coord.md for memory ordering // considerations. bool ReadFlag(ThreadFlag flag, std::memory_order order) const { return GetStateAndFlags(order).IsFlagSet(flag);
}
void AtomicSetFlag(ThreadFlag flag, std::memory_order order = std::memory_order_seq_cst) { // Since we discard the returned value, memory_order_release will often suffice.
tls32_.state_and_flags.fetch_or(enum_cast<uint32_t>(flag), order);
}
void AtomicClearFlag(ThreadFlag flag, std::memory_order order = std::memory_order_seq_cst) { // Since we discard the returned value, memory_order_release will often suffice.
tls32_.state_and_flags.fetch_and(~enum_cast<uint32_t>(flag), order);
}
void ResetQuickAllocEntryPointsForThread();
// Returns the remaining space in the TLAB.
size_t TlabSize() const { return tlsPtr_.thread_local_end - tlsPtr_.thread_local_pos;
}
// Returns the remaining space in the TLAB if we were to expand it to maximum capacity.
size_t TlabRemainingCapacity() const { return tlsPtr_.thread_local_limit - tlsPtr_.thread_local_pos;
}
// Expand the TLAB by a fixed number of bytes. There must be enough capacity to do so. void ExpandTlab(size_t bytes) {
tlsPtr_.thread_local_end += bytes;
DCHECK_LE(tlsPtr_.thread_local_end, tlsPtr_.thread_local_limit);
}
// Called from Concurrent mark-compact GC to slide the TLAB pointers backwards // to adjust to post-compact addresses. void AdjustTlab(size_t slide_bytes);
// Doesn't check that there is room.
mirror::Object* AllocTlab(size_t bytes); void SetTlab(uint8_t* start, uint8_t* end, uint8_t* limit); bool HasTlab() const; void ResetTlab();
uint8_t* GetTlabStart() { return tlsPtr_.thread_local_start;
}
uint8_t* GetTlabPos() { return tlsPtr_.thread_local_pos;
}
uint8_t* GetTlabEnd() { return tlsPtr_.thread_local_end;
} // Remove the suspend trigger for this thread by making the suspend_trigger_ TLS value // equal to a valid pointer. void RemoveSuspendTrigger() {
tlsPtr_.suspend_trigger.store(reinterpret_cast<uintptr_t*>(&tlsPtr_.suspend_trigger),
std::memory_order_relaxed);
} // Check the suspend trigger value. This is not the way we normally check for suspension, but // can be used to explicitly propagate the value to the suspend check register. bool IsSuspendTriggerSet() { return tlsPtr_.suspend_trigger.load(std::memory_order_relaxed) == nullptr;
}
// Trigger a suspend check by making the suspend_trigger_ TLS value an invalid pointer. // The next time a suspend check is done, it will load from the value at this address // and trigger a SIGSEGV. // Only needed if Runtime::implicit_suspend_checks_ is true. On some platforms, and in the // interpreter, client code currently just looks at the thread flags directly to determine // whether we should suspend, so this call is not always necessary. void TriggerSuspend() { tlsPtr_.suspend_trigger.store(nullptr, std::memory_order_release); }
// Push an object onto the allocation stack. bool PushOnThreadLocalAllocationStack(mirror::Object* obj)
REQUIRES_SHARED(Locks::mutator_lock_);
// Set the thread local allocation pointers to the given pointers. void SetThreadLocalAllocationStack(StackReference<mirror::Object>* start,
StackReference<mirror::Object>* end);
// Resets the thread local allocation pointers. void RevokeThreadLocalAllocationStack();
bool IsForceInterpreter() const {
DCHECK(this == Thread::Current() || IsSuspended() ||
Locks::thread_list_lock_->IsExclusiveHeld(Thread::Current()))
<< "Please suspend this thread or acquire thread_list_lock from another thread. "
<< "See the doc of mounted_virtual_thread_data field for details."; return (tls32_.force_interpreter_count != 0) ||
tlsPtr_.mounted_virtual_thread_data.load(std::memory_order_relaxed) != nullptr;
}
// Gets the current TLSData associated with the key or nullptr if there isn't any. Note that users // do not gain ownership of TLSData and must synchronize with SetCustomTls themselves to prevent // it from being deleted.
TLSData* GetCustomTLS(constchar* key) REQUIRES(!Locks::custom_tls_lock_);
// Sets the tls entry at 'key' to data. The thread takes ownership of the TLSData. The destructor // will be run when the thread exits or when SetCustomTLS is called again with the same key. void SetCustomTLS(constchar* key, TLSData* data) REQUIRES(!Locks::custom_tls_lock_);
// Returns true if the current thread is the jit sensitive thread. bool IsJitSensitiveThread() const { returnthis == jit_sensitive_thread_;
}
// Cause the 'this' thread to abort the process by sending SIGABRT. Thus we should get an // asynchronous stack trace for 'this' thread, rather than waiting for it to process a // checkpoint. Useful mostly to discover why a thread isn't responding to a suspend request or // checkpoint. The caller should "suspend" (in the Java sense) 'thread' before invoking this, so // 'thread' can't get deallocated before we access it.
NO_RETURN void AbortInThis(const std::string& message);
// Returns true if StrictMode events are traced for the current thread. staticbool IsSensitiveThread() { if (is_sensitive_thread_hook_ != nullptr) { return (*is_sensitive_thread_hook_)();
} returnfalse;
}
// Set to the read barrier marking entrypoints to be non-null. void SetReadBarrierEntrypoints();
// Clear all thread-local interpreter caches. // // Since the caches are keyed by memory pointer to dex instructions, this must be // called when any dex code is unloaded (before different code gets loaded at the // same memory location). // // If presence of cache entry implies some pre-conditions, this must also be // called if the pre-conditions might no longer hold true. staticvoid ClearAllInterpreterCaches();
// Set nice value before temporary priority boost, for use by ScopedPriorityChange. void SetNicenessBeforeBoost(int niceness) {
DCHECK(niceness == kNotBoosted || (niceness >= -20 && niceness <= 19));
niceness_before_boost_ = static_cast<int8_t>(niceness);
}
int GetNicenessBeforeBoost() { return niceness_before_boost_; }
private: // We pretend to acquire this while running a checkpoint to detect lock ordering issues. // Initialized lazily. static std::atomic<Mutex*> cp_placeholder_mutex_;
explicit Thread(bool daemon);
// A successfully started thread is only deleted by the thread itself. // Threads are deleted after they have been removed from the thread list while holding // suspend_count_lock_ and thread_list_lock_. We refuse to do this while either kSuspendRequest // or kRunningFlipFunction are set. We can prevent Thread destruction by holding either of those // locks, ensuring that either of those flags are set, or possibly by registering and checking a // ThreadExitFlag.
~Thread() REQUIRES(!Locks::mutator_lock_, !Locks::thread_suspend_count_lock_);
// Thread destruction actions that do not invalidate the thread. Checkpoints and flip_functions // may still be called on this Thread object, though not by this thread, during and after the // Destroy() call. void Destroy(bool should_run_callbacks);
// Deletes and clears the tlsPtr_.jpeer field. Done in a way so that both it and opeer cannot be // observed to be set at the same time by instrumentation. void DeleteJPeer(JNIEnv* env);
// Attaches the calling native thread to the runtime, returning the new native peer. // Used to implement JNI AttachCurrentThread and AttachCurrentThreadAsDaemon calls. template <typename PeerAction> static Thread* Attach(constchar* thread_name, bool as_daemon,
PeerAction p, bool should_run_callbacks);
// Avoid use, callers should use SetState. // Used only by `Thread` destructor and stack trace collection in semi-space GC (currently // disabled by `kStoreStackTraces = false`). May not be called on a runnable thread other // than Thread::Current(). // NO_THREAD_SAFETY_ANALYSIS: This function is "Unsafe" and can be called in // different states, so clang cannot perform the thread safety analysis.
ThreadState SetStateUnsafe(ThreadState new_state) NO_THREAD_SAFETY_ANALYSIS {
StateAndFlags old_state_and_flags = GetStateAndFlags(std::memory_order_relaxed);
ThreadState old_state = old_state_and_flags.GetState(); if (old_state == new_state) { // Nothing to do.
} elseif (old_state == ThreadState::kRunnable) {
DCHECK_EQ(this, Thread::Current()); // Need to run pending checkpoint and suspend barriers. Run checkpoints in runnable state in // case they need to use a ScopedObjectAccess. If we are holding the mutator lock and a SOA // attempts to TransitionFromSuspendedToRunnable, it results in a deadlock.
TransitionToSuspendedAndRunCheckpoints(new_state); // Since we transitioned to a suspended state, check the pass barrier requests.
CheckActiveSuspendBarriers();
} else { while (true) {
StateAndFlags new_state_and_flags = old_state_and_flags;
new_state_and_flags.SetState(new_state); if (LIKELY(tls32_.state_and_flags.CompareAndSetWeakAcquire(
old_state_and_flags.GetValue(), new_state_and_flags.GetValue()))) { break;
} // Reload state and flags.
old_state_and_flags = GetStateAndFlags(std::memory_order_relaxed);
DCHECK_EQ(old_state, old_state_and_flags.GetState());
}
} return old_state;
}
// Out-of-line conveniences for debugging in gdb. static Thread* CurrentFromGdb(); // Like Thread::Current. // Like Thread::Dump(std::cerr). void DumpFromGdb() const REQUIRES_SHARED(Locks::mutator_lock_);
// A wrapper around CreateCallback used when userfaultfd GC is used to // identify the GC by stacktrace. static NO_INLINE void* CreateCallbackWithUffdGc(void* arg); staticvoid* CreateCallback(void* arg);
// Initialize a thread. // // The third parameter is not mandatory. If given, the thread will use this JNIEnvExt. In case // Init succeeds, this means the thread takes ownership of it. If Init fails, it is the caller's // responsibility to destroy the given JNIEnvExt. If the parameter is null, Init will try to // create a JNIEnvExt on its own (and potentially fail at that stage, indicated by a return value // of false). bool Init(ThreadList*, JavaVMExt*, JNIEnvExt* jni_env_ext = nullptr)
REQUIRES(Locks::runtime_shutdown_lock_); void InitCardTable(); void InitCpu();
// Call PassActiveSuspendBarriers() if there are active barriers. Only called on current thread.
ALWAYS_INLINE void CheckActiveSuspendBarriers()
REQUIRES(!Locks::thread_suspend_count_lock_, !Locks::mutator_lock_, !Roles::uninterruptible_);
// Decrement all "suspend barriers" for the current thread, notifying threads that requested our // suspension. Only called on current thread, when suspended. If suspend_count_ > 0 then we // promise that we are and will remain "suspended" until the suspend count is decremented. bool PassActiveSuspendBarriers()
REQUIRES(!Locks::thread_suspend_count_lock_, !Locks::mutator_lock_);
// Add an entry to active_suspend1_barriers.
ALWAYS_INLINE void AddSuspend1Barrier(WrappedSuspend1Barrier* suspend1_barrier)
REQUIRES(Locks::thread_suspend_count_lock_);
// Remove last-added entry from active_suspend1_barriers. // Only makes sense if we're still holding thread_suspend_count_lock_ since insertion. // We redundantly pass in the barrier to be removed in order to enable a DCHECK.
ALWAYS_INLINE void RemoveFirstSuspend1Barrier(WrappedSuspend1Barrier* suspend1_barrier)
REQUIRES(Locks::thread_suspend_count_lock_);
// Remove the "barrier" from the list no matter where it appears. Called only under exceptional // circumstances. The barrier must be in the list.
ALWAYS_INLINE void RemoveSuspend1Barrier(WrappedSuspend1Barrier* suspend1_barrier)
REQUIRES(Locks::thread_suspend_count_lock_);
// CHECK that the given barrier is no longer on our list.
ALWAYS_INLINE void CheckBarrierInactive(WrappedSuspend1Barrier* suspend1_barrier)
REQUIRES(Locks::thread_suspend_count_lock_);
// Registers the current thread as the jit sensitive thread. Should be called just once. staticvoid SetJitSensitiveThread() { if (jit_sensitive_thread_ == nullptr) {
jit_sensitive_thread_ = Thread::Current();
} else {
LOG(WARNING) << "Attempt to set the sensitive thread twice. Tid:"
<< Thread::Current()->GetTid();
}
}
// Runs a single checkpoint function. If there are no more pending checkpoint functions it will // clear the kCheckpointRequest flag. The caller is responsible for calling this in a loop until // the kCheckpointRequest flag is cleared. void RunCheckpointFunction()
REQUIRES(!Locks::thread_suspend_count_lock_)
REQUIRES_SHARED(Locks::mutator_lock_); void RunEmptyCheckpoint();
// Install the protected region for implicit stack checks. template <StackType> void InstallImplicitProtection();
// Helper class for manipulating the 32 bits of atomically changed state and flags. class StateAndFlags { public: explicit StateAndFlags(uint32_t value) :value_(value) {}
// Format state and flags as a hex string. For diagnostic output.
std::string StateAndFlagsAsHexString() const;
// Run the flip function and notify other threads that may have tried // to do that concurrently. void RunFlipFunction(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
// Ensure that thread flip function for thread target started running. If no other thread is // executing it, the calling thread shall run the flip function and then notify other threads // that have tried to do that concurrently. After this function returns, the // `ThreadFlag::kPendingFlipFunction` is cleared but another thread may still be running the // flip function as indicated by the `ThreadFlag::kRunningFlipFunction`. Optional arguments: // - old_state_and_flags indicates the current and state and flags value for the thread, with // at least kPendingFlipFunction set. The thread should logically acquire the // mutator lock before running the flip function. A special zero value indicates that the // thread already holds the mutator lock, and the actual state_and_flags must be read. // A non-zero value implies this == Current(). // - If tef is non-null, we check that the target thread has not yet exited, as indicated by // tef. In that case, we acquire thread_list_lock_ as needed. // - If finished is non-null, we assign to *finished to indicate whether the flip was known to // be completed when we returned. // Returns true if and only if we acquired the mutator lock (which implies that we ran the flip // function after finding old_state_and_flags unchanged). staticbool EnsureFlipFunctionStarted(Thread* self,
Thread* target,
StateAndFlags old_state_and_flags = StateAndFlags(0),
ThreadExitFlag* tef = nullptr, /*out*/ bool* finished = nullptr)
REQUIRES(!Locks::thread_list_lock_) TRY_ACQUIRE_SHARED(true, Locks::mutator_lock_);
staticvoid ThreadExitCallback(void* arg);
// Maximum number of suspend barriers. static constexpr uint32_t kMaxSuspendBarriers = 3;
// Has Thread::Startup been called? staticbool is_started_;
// TLS key used to retrieve the Thread*. static pthread_key_t pthread_key_self_;
// Used to notify threads that they should attempt to resume, they will suspend again if // their suspend count is > 0. static ConditionVariable* resume_cond_ GUARDED_BY(Locks::thread_suspend_count_lock_);
// Hook passed by framework which returns true // when StrictMode events are traced for the current thread. staticbool (*is_sensitive_thread_hook_)(); // Stores the jit sensitive thread (which for now is the UI thread).
LIBART_PROTECTED static Thread* jit_sensitive_thread_;
/***********************************************************************************************/ // Thread local storage. Fields are grouped by size to enable 32 <-> 64 searching to account for // pointer size differences. To encourage shorter encoding, more frequently used values appear // first if possible. /***********************************************************************************************/
struct alignas(4) tls_32bit_sized_values { // We have no control over the size of 'bool', but want our boolean fields // to be 4-byte quantities. using bool32_t = uint32_t;
// The state and flags field must be changed atomically so that flag values aren't lost. // See `StateAndFlags` for bit assignments of `ThreadFlag` and `ThreadState` values. // Keeping the state and flags together allows an atomic CAS to change from being // Suspended to Runnable without a suspend request occurring.
Atomic<uint32_t> state_and_flags;
static_assert(sizeof(state_and_flags) == sizeof(uint32_t), "Size of state_and_flags and uint32 are different");
// A non-zero value is used to tell the current thread to enter a safe point // at the next poll. int suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);
// Thin lock thread id. This is a small integer used by the thin lock implementation. // This is not to be confused with the native thread's tid, nor is it the value returned // by java.lang.Thread.getId --- this is a distinct value, used only for locking. One // important difference between this id and the ids visible to managed code is that these // ones get reused (to ensure that they fit in the number of bits available).
uint32_t thin_lock_thread_id;
// System thread id.
uint32_t tid;
// Is the thread a daemon? const bool32_t daemon;
// A boolean telling us whether we're recursively throwing OOME.
bool32_t throwing_OutOfMemoryError;
// A positive value implies we're in a region where thread suspension isn't expected.
uint32_t no_thread_suspension;
// How many times has our pthread key's destructor been called?
uint32_t thread_exit_check_count;
// True if the GC is in the marking phase. This is used for the CC collector only. This is // thread local so that we can simplify the logic to check for the fast path of read barriers of // GC roots.
bool32_t is_gc_marking;
// True if we need to check for deoptimization when returning from the runtime functions. This // is required only when a class is redefined to prevent executing code that has field offsets // embedded. For non-debuggable apps redefinition is not allowed and this flag should always be // set to false.
bool32_t is_deopt_check_required;
// Thread "interrupted" status; stays raised until queried or thrown.
Atomic<bool32_t> interrupted;
AtomicInteger park_state_;
// Determines whether the thread is allowed to directly access a weak ref // (Reference::GetReferent() and system weaks) and to potentially mark an object alive/gray. // This is used for concurrent reference processing of the CC collector only. This is thread // local so that we can enable/disable weak ref access by using a checkpoint and avoid a race // around the time weak ref access gets disabled and concurrent reference processing begins // (if weak ref access is disabled during a pause, this is not an issue.) Other collectors use // Runtime::DisallowNewSystemWeaks() and ReferenceProcessor::EnableSlowPath(). Can be // concurrently accessed by GetReferent() and set (by iterating over threads). // Can be changed from kEnabled to kVisiblyEnabled by readers. No other concurrent access is // possible when that happens. mutable std::atomic<WeakRefAccessState> weak_ref_access_enabled;
// A thread local version of Heap::disable_thread_flip_count_. This keeps track of how many // levels of (nested) JNI critical sections the thread is in and is used to detect a nested JNI // critical section enter.
uint32_t disable_thread_flip_count;
// How much of 'suspend_count_' is by request of user code, used to distinguish threads // suspended by the runtime from those suspended by user code. // This should have GUARDED_BY(Locks::user_code_suspension_lock_) but auto analysis cannot be // told that AssertHeld should be good enough. int user_code_suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);
// Count of how many times this thread has been forced to interpreter. If this is not 0 the // thread must remain in interpreted code as much as possible.
uint32_t force_interpreter_count;
// Counter for calls to initialize a class that's initialized but not visibly initialized. // When this reaches kMakeVisiblyInitializedCounterTriggerCount, we call the runtime to // make initialized classes visibly initialized. This is needed because we usually make // classes visibly initialized in batches but we do not want to be stuck with a class // initialized but not visibly initialized for a long time even if no more classes are // being initialized anymore.
uint32_t make_visibly_initialized_counter;
// Counter for how many nested define-classes are ongoing in this thread. Used to allow waiting // for threads to be done with class-definition work.
uint32_t define_class_counter;
// A count of the number of readers of tlsPtr_.name that may still be looking at a string they // retrieved. mutable std::atomic<uint32_t> num_name_readers;
static_assert(std::atomic<uint32_t>::is_always_lock_free);
// Thread-local hotness counter for shared memory methods. Initialized with // `kSharedMethodHotnessThreshold`. The interpreter decrements it and goes // into the runtime when hitting zero. Note that all previous decrements // could have been executed by another method than the one seeing zero. // There is a second level counter in `Jit::shared_method_counters_` to make // sure we at least have a few samples before compiling a method.
uint32_t shared_method_hotness;
} tls32_;
// The biased card table, see CardTable for details.
uint8_t* card_table;
// The pending exception or null.
mirror::Throwable* exception;
// The end of this thread's stack. This is the lowest safely-addressable address on the stack. // We leave extra space so there's room for the code that throws StackOverflowError. // Note: do not use directly, instead use GetStackEnd/SetStackEnd template function instead.
uint8_t* stack_end;
// The top of the managed stack often manipulated directly by compiler generated code.
ManagedStack managed_stack;
// In certain modes, setting this to 0 will trigger a SEGV and thus a suspend check. It is // normally set to the address of itself. It should be cleared with release semantics to ensure // that prior state changes etc. are visible to any thread that faults as a result. // We assume that the kernel ensures that such changes are then visible to the faulting // thread, even if it is not an acquire load that faults. (Indeed, it seems unlikely that the // ordering semantics associated with the faulting load has any impact.)
std::atomic<uintptr_t*> suspend_trigger;
// Every thread may have an associated JNI environment
JNIEnvExt* jni_env;
// Temporary storage to transfer a pre-allocated JNIEnvExt from the creating thread to the // created thread.
JNIEnvExt* tmp_jni_env;
// Initialized to "this". On certain architectures (such as x86) reading off of Thread::Current // is easy but getting the address of Thread::Current is hard. This field can be read off of // Thread::Current to give the address.
Thread* self;
// Our managed peer (an instance of java.lang.Thread). The jobject version is used during thread // start up, until the thread is registered and the local opeer_ is used.
mirror::Object* opeer;
jobject jpeer;
// The "lowest addressable byte" of the stack. // Note: do not use directly, instead use GetStackBegin/SetStackBegin template function instead.
uint8_t* stack_begin;
// Size of the stack. // Note: do not use directly, instead use GetStackSize/SetStackSize template function instead.
size_t stack_size;
// Sampling profiler and AOT verification cannot happen on the same run, so we share // the same entry for the stack trace and the verifier deps. union DepsOrStackTraceSample {
DepsOrStackTraceSample() {
verifier_deps = nullptr;
stack_trace_sample = nullptr;
} // Pointer to previous stack trace captured by sampling profiler.
std::vector<ArtMethod*>* stack_trace_sample; // When doing AOT verification, per-thread VerifierDeps.
verifier::VerifierDeps* verifier_deps;
} deps_or_stack_trace_sample;
// The next thread in the wait set this thread is part of or null if not waiting.
Thread* wait_next;
// If we're blocked in MonitorEnter, this is the object we're trying to lock.
mirror::Object* monitor_enter_object;
// Top of linked list of handle scopes or null for none.
BaseHandleScope* top_handle_scope;
// Needed to get the right ClassLoader in JNI_OnLoad, but also // useful for testing.
jobject class_loader_override;
// For gc purpose, a shadow frame record stack that keeps track of: // 1) shadow frames under construction. // 2) deoptimization shadow frames.
StackedShadowFrameRecord* stacked_shadow_frame_record;
// Deoptimization return value record stack.
DeoptimizationContextRecord* deoptimization_context_stack;
// For debugger, a linked list that keeps the mapping from frame_id to shadow frame. // Shadow frames may be created before deoptimization happens so that the debugger can // set local values there first.
FrameIdToShadowFrame* frame_id_to_shadow_frame;
// A cached copy of the java.lang.Thread's (modified UTF-8) name. // If this is not null or kThreadNameDuringStartup, then it owns the malloc memory holding // the string. Updated in an RCU-like manner.
std::atomic<constchar*> name;
static_assert(std::atomic<constchar*>::is_always_lock_free);
// A cached pthread_t for the pthread underlying this Thread*.
pthread_t pthread_self;
// After a thread observes a suspend request and enters a suspended state, // it notifies the requestor by arriving at a "suspend barrier". This consists of decrementing // the atomic integer representing the barrier. (This implementation was introduced in 2015 to // minimize cost. There may be other options.) These atomic integer barriers are always // stored on the requesting thread's stack. They are referenced from the target thread's // data structure in one of two ways; in either case the data structure referring to these // barriers is guarded by suspend_count_lock: // 1. A SuspendAll barrier is directly referenced from the target thread. Only one of these // can be active at a time:
AtomicInteger* active_suspendall_barrier GUARDED_BY(Locks::thread_suspend_count_lock_); // 2. For individual thread suspensions, active barriers are embedded in a struct that is used // to link together all suspend requests for this thread. Unlike the SuspendAll case, each // barrier is referenced by a single target thread, and thus can appear only on a single list. // The struct as a whole is still stored on the requesting thread's stack.
WrappedSuspend1Barrier* active_suspend1_barriers GUARDED_BY(Locks::thread_suspend_count_lock_);
// thread_local_pos and thread_local_end must be consecutive for ldrd and are 8 byte aligned for // potentially better performance.
uint8_t* thread_local_pos;
uint8_t* thread_local_end;
// Thread-local allocation pointer. Can be moved above the preceding two to correct alignment.
uint8_t* thread_local_start;
// Thread local limit is how much we can expand the thread local buffer to, it is greater or // equal to thread_local_end.
uint8_t* thread_local_limit;
size_t thread_local_objects;
// Pending checkpoint function or null if non-pending. If this checkpoint is set and someone // requests another checkpoint, it goes to the checkpoint overflow list.
Closure* checkpoint_function GUARDED_BY(Locks::thread_suspend_count_lock_);
// Entrypoint function pointers. // TODO: move this to more of a global offset table model to avoid per-thread duplication.
JniEntryPoints jni_entrypoints;
QuickEntryPoints quick_entrypoints;
// There are RosAlloc::kNumThreadLocalSizeBrackets thread-local size brackets per thread. void* rosalloc_runs[kNumRosAllocThreadLocalSizeBracketsInThread];
// Pointer to the mutator lock. // This is the same as `Locks::mutator_lock_` but cached for faster state transitions.
MutatorMutex* mutator_lock;
// Support for Mutex lock hierarchy bug detection.
BaseMutex* held_mutexes[kLockLevelCount];
// The function used for thread flip. Set while holding Locks::thread_suspend_count_lock_ and // with all other threads suspended. May be cleared while being read.
std::atomic<Closure*> flip_function;
union { // Thread-local mark stack for the concurrent copying collector.
gc::accounting::AtomicStack<mirror::Object>* thread_local_mark_stack; // Thread-local page-sized buffer for userfaultfd GC.
uint8_t* thread_local_gc_buffer;
};
// The pending async-exception or null.
mirror::Throwable* async_exception;
// Top of the linked-list for reflective-handle scopes or null if none.
BaseReflectiveHandleScope* top_reflective_handle_scope;
// Pointer to a thread-local buffer for method tracing.
uintptr_t* method_trace_buffer;
// Pointer to the current entry in the buffer.
uintptr_t* method_trace_buffer_curr_entry;
// Pointer to the first node of an intrusively doubly-linked list of ThreadExitFlags.
ThreadExitFlag* thread_exit_flags GUARDED_BY(Locks::thread_list_lock_);
// If no_thread_suspension_ is > 0, what is causing that assertion. constchar* last_no_thread_suspension_cause;
// If the thread is asserting that there should be no transaction checks, // what is causing that assertion (debug builds only). constchar* last_no_transaction_checks_cause;
#ifdef ART_USE_SIMULATOR struct SimulatorData {
SimulatorData()
: sim_executor(nullptr),
sim_stack_end(nullptr),
sim_stack_begin(nullptr),
sim_stack_size(0) {} // Each thread has its own simulator executor with a full sim CPU context: registers, // stack, etc.
CodeSimulator* sim_executor;
// Same semantics as for the relevant stack variables (see the diagram near class Thread), but // for simulator's stack.
uint8_t* sim_stack_end;
uint8_t* sim_stack_begin;
size_t sim_stack_size;
} sim_data; #endif
// Hold either the same reference as opeer or a VirtualThread instance. Mainly used for the // java.lang.Thread.currentThread() API.
mirror::Object* current_peer;
// This field is normally set when virtual thread is mounted, and the object is expected // to be allocated in the stack. When no virtual thread is mounted on this platform thread, // the value should be nullptr. // The concurrency model: // 1. This atomic value is expected to be modified by the thread itself while holding // thread_list_lock_ and mutator_lock_ only. // 2. The flags_ field should only be accessed by the thread itself. // 3. Accessing the next_ field requires thread_list_lock_. // 4. Accessing other fields or reliably performing a null check on this field from other // threads requires thread_list_lock_ or a thread suspension. // 5. For limited purposes, e.g. logging or DCHECK, where holding thread_list_lock_ or // a thread suspension is challenging, an atomic null check from other threads // provides a useful hint whether a virtual thread is mounted on another platform thread, but // it is not reliable.
std::atomic<MountedVirtualThreadData*> mounted_virtual_thread_data;
} tlsPtr_;
// Small thread-local cache to be used from the interpreter. // It is keyed by dex instruction pointer. // The value is opcode-depended (e.g. field offset).
InterpreterCache interpreter_cache_;
// All fields below this line should not be accessed by native code. This means these fields can // be modified, rearranged, added or removed without having to modify asm_support.h
// Guards the 'wait_monitor_' members.
Mutex* wait_mutex_ DEFAULT_MUTEX_ACQUIRED_AFTER;
// Condition variable waited upon during a wait.
ConditionVariable* wait_cond_ GUARDED_BY(wait_mutex_); // Pointer to the monitor lock we're currently waiting on or null if not waiting.
Monitor* wait_monitor_ GUARDED_BY(wait_mutex_);
// Debug disable read barrier count, only is checked for debug builds and only in the runtime.
uint8_t debug_disallow_read_barrier_ = 0;
// Counters used only for debugging and error reporting. Likely to wrap. Small to avoid // increasing Thread size. // We currently maintain these unconditionally, since it doesn't cost much, and we seem to have // persistent issues with suspension timeouts, which these should help to diagnose. // TODO: Reconsider this.
std::atomic<uint8_t> suspended_count_ = 0; // Number of times we entered a suspended state after // running checkpoints.
std::atomic<uint8_t> checkpoint_count_ = 0; // Number of checkpoints we started running.
// Note that it is not in the packed struct, may not be accessed for cross compilation.
uintptr_t poison_object_cookie_ = 0;
// Pending extra checkpoints if checkpoint_function_ is already used.
std::list<Closure*> checkpoint_overflow_ GUARDED_BY(Locks::thread_suspend_count_lock_);
// Custom TLS field that can be used by plugins or the runtime. Should not be accessed directly by // compiled code or entrypoints.
SafeMap<std::string, std::unique_ptr<TLSData>, std::less<>> custom_tls_
GUARDED_BY(Locks::custom_tls_lock_);
// True if the thread is some form of runtime thread (ex, GC or JIT). bool is_runtime_thread_;
// Priority before ScopedPriorityChange::SetToNormalOrBetter, or kNotBoosted.
int8_t niceness_before_boost_ = kNotBoosted;
// Set during execution of JNI methods that get field and method id's as part of determining if // the caller is allowed to access all fields and methods in the Core Platform API.
uint32_t core_platform_api_cookie_ = 0;
friendclass gc::collector::SemiSpace; // For getting stack traces. friendclass Runtime; // For CreatePeer. friendclass QuickExceptionHandler; // For dumping the stack. friendclass ScopedAssertNoTransactionChecks; friendclass ScopedThreadStateChange; friendclass StubTest; // For accessing entrypoints. friendclass ThreadList; // For ~Thread, Destroy and EnsureFlipFunctionStarted. friendclass EntrypointsOrderTest; // To test the order of tls entries. friendclass JniCompilerTest; // For intercepting JNI entrypoint calls.
DISALLOW_COPY_AND_ASSIGN(Thread);
}; // The least significant bit of Thread* is used for virtual thread ids in art::MonitorMutex.
static_assert(alignof(Thread) >= 2, "Thread must be aligned to a minimum of 2 bytes");
// Only works for debug builds. class ScopedDebugDisallowReadBarriers { public: explicit ScopedDebugDisallowReadBarriers(Thread* self) : self_(self) { // Note: If there is no `Thread`, read barriers are not allowed. if (kCheckDebugDisallowReadBarrierCount && self_ != nullptr) {
self_->ModifyDebugDisallowReadBarrier(1);
}
}
~ScopedDebugDisallowReadBarriers() { if (kCheckDebugDisallowReadBarrierCount && self_ != nullptr) {
self_->ModifyDebugDisallowReadBarrier(-1);
}
}
private:
Thread* const self_;
};
class ThreadLifecycleCallback { public: virtual ~ThreadLifecycleCallback() {}
// Store an exception from the thread and suppress it for the duration of this object. class ScopedExceptionStorage { public:
EXPORT explicit ScopedExceptionStorage(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); void SuppressOldException(constchar* message = "") REQUIRES_SHARED(Locks::mutator_lock_);
EXPORT ~ScopedExceptionStorage() REQUIRES_SHARED(Locks::mutator_lock_);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.