Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/runtime/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 7 kB image not shown  

Quelle  scoped_thread_state_change.h

  Sprache: C
 

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_

#include "jni.h"

#include "base/locks.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "thread_state.h"

namespace art HIDDEN {

class JavaVMExt;
class JNIEnvExt;
template<class MirrorType> class ObjPtr;
class Thread;

namespace mirror {
class Object;
}  // namespace mirror

// Scoped change into and out of a particular state. Handles Runnable transitions that require
// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
// the unchecked variant doesn't aid annotalysis.
class ScopedThreadStateChange : public ValueObject {
 public:
  ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE Thread* Self() const {
    return self_;
  }

 protected:
  // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
  ScopedThreadStateChange() {}

  Thread* const self_ = nullptr;
  const ThreadState thread_state_ = ThreadState::kTerminated;

 private:
  EXPORT void ScopedThreadChangeDestructorCheck();

  ThreadState old_thread_state_ = ThreadState::kTerminated;
  const bool expected_has_no_thread_ = true;

  friend class ScopedObjectAccessUnchecked;
  DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
};

// Assumes we are already runnable.
class ScopedObjectAccessAlreadyRunnable : public ValueObject {
 public:
  Thread* Self() const {
    return self_;
  }

  JNIEnvExt* Env() const {
    return env_;
  }

  JavaVMExt* Vm() const {
    return vm_;
  }

  bool ForceCopy() const;

  /*
   * Add a local reference for an object to the indirect reference table associated with the
   * current stack frame.  When the native function returns, the reference will be discarded.
   *
   * We need to allow the same reference to be added multiple times, and cope with nullptr.
   *
   * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
   * it's best if we don't grab a mutex.
   */

  template<typename T>
  T AddLocalReference(ObjPtr<mirror::Object> obj) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  template<typename T>
  ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);

  ALWAYS_INLINE bool IsRunnable() const;

 protected:
  ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
  // change into Runnable or acquire a share on the mutator_lock_.
  // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
  //       as it prevents forward declaration of JavaVMExt.
  explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
      : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}

  // Here purely to force inlining.
  ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}

  static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Self thread, can be null.
  Thread* const self_;
  // The full JNIEnv.
  JNIEnvExt* const env_;
  // The full JavaVM.
  JavaVMExt* const vm_;
};

// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
//
// This class performs the necessary thread state switching to and from Runnable and lets us
// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
// is also manipulating the Object.
//
// The destructor transitions back to the previous thread state, typically Native. In this state
// GC and thread suspension may occur.
//
// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
// the mutator_lock_ will be acquired on construction.
class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
 public:
  ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {}

  // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
  // change into Runnable or acquire a share on the mutator_lock_.
  explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
      : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}

 private:
  // The scoped thread state change makes sure that we are runnable and restores the thread state
  // in the destructor.
  const ScopedThreadStateChange tsc_;

  DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
};

// Annotalysis helping variant of the above.
class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
 public:
  ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_)
      SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_)
      SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

  // Base class will release share of lock. Invoked after this destructor.
  ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE;

 private:
  // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
  //       routines operating with just a VM are sound, they are not, but when you have just a VM
  //       you cannot call the unsound routines.
  explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
      : ScopedObjectAccessUnchecked(vm) {}

  friend class ScopedCheck;
  DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
};

// Annotalysis helper for going to a suspended state from runnable.
class ScopedThreadSuspension : public ValueObject {
 public:
  ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
      REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
      UNLOCK_FUNCTION(Locks::mutator_lock_);

  ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

 private:
  Thread* const self_;
  const ThreadState suspended_state_;
  DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
};

}  // namespace art

#endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_

Messung V0.5 in Prozent
C=88 H=93 G=90

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.