diff options
Diffstat (limited to 'runtime/monitor.h')
-rw-r--r-- | runtime/monitor.h | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/runtime/monitor.h b/runtime/monitor.h new file mode 100644 index 0000000..9194c08 --- /dev/null +++ b/runtime/monitor.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2008 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_SRC_MONITOR_H_ +#define ART_SRC_MONITOR_H_ + +#include <pthread.h> +#include <stdint.h> + +#include <iosfwd> +#include <list> +#include <vector> + +#include "base/mutex.h" +#include "root_visitor.h" +#include "thread_state.h" + +namespace art { + +/* + * Monitor shape field. Used to distinguish thin locks from fat locks. + */ +#define LW_SHAPE_THIN 0 +#define LW_SHAPE_FAT 1 + +/* + * Hash state field. Used to signify that an object has had its + * identity hash code exposed or relocated. + */ +#define LW_HASH_STATE_UNHASHED 0 +#define LW_HASH_STATE_HASHED 1 +#define LW_HASH_STATE_HASHED_AND_MOVED 3 +#define LW_HASH_STATE_MASK 0x3 +#define LW_HASH_STATE_SHIFT 1 +#define LW_HASH_STATE(x) (((x) >> LW_HASH_STATE_SHIFT) & LW_HASH_STATE_MASK) + +/* + * Lock owner field. Contains the thread id of the thread currently + * holding the lock. + */ +#define LW_LOCK_OWNER_MASK 0xffff +#define LW_LOCK_OWNER_SHIFT 3 +#define LW_LOCK_OWNER(x) (((x) >> LW_LOCK_OWNER_SHIFT) & LW_LOCK_OWNER_MASK) + +namespace mirror { +class AbstractMethod; +class Object; +} // namespace mirror +class Thread; +class StackVisitor; + +class Monitor { + public: + ~Monitor(); + + static bool IsSensitiveThread(); + static void Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread_hook)()); + + static uint32_t GetThinLockId(uint32_t raw_lock_word) + NO_THREAD_SAFETY_ANALYSIS; // Reading lock owner without holding lock is racy. + + static void MonitorEnter(Thread* thread, mirror::Object* obj) + EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static bool MonitorExit(Thread* thread, mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + UNLOCK_FUNCTION(monitor_lock_); + + static void Notify(Thread* self, mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static void NotifyAll(Thread* self, mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static void Wait(Thread* self, mirror::Object* obj, int64_t ms, int32_t ns, + bool interruptShouldThrow, ThreadState why) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static void DescribeWait(std::ostream& os, const Thread* thread) + LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Used to implement JDWP's ThreadReference.CurrentContendedMonitor. + static mirror::Object* GetContendedMonitor(Thread* thread); + + // Calls 'callback' once for each lock held in the single stack frame represented by + // the current state of 'stack_visitor'. + static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), + void* callback_context) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + mirror::Object* GetObject(); + + private: + explicit Monitor(Thread* owner, mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void AppendToWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_); + void RemoveFromWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_); + + static void Inflate(Thread* self, mirror::Object* obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, + const char* owner_filename, uint32_t owner_line_number) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static void FailedUnlock(mirror::Object* obj, Thread* expected_owner, Thread* found_owner, Monitor* mon) + LOCKS_EXCLUDED(Locks::thread_list_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(monitor_lock_); + bool Unlock(Thread* thread, bool for_wait) UNLOCK_FUNCTION(monitor_lock_); + + void Notify(Thread* self) NO_THREAD_SAFETY_ANALYSIS; + void NotifyWithLock(Thread* self) + EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void NotifyAll(Thread* self) NO_THREAD_SAFETY_ANALYSIS; + void NotifyAllWithLock() + EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + + void Wait(Thread* self, int64_t msec, int32_t nsec, bool interruptShouldThrow, ThreadState why) + NO_THREAD_SAFETY_ANALYSIS; + void WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThrow, ThreadState why) + EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Translates the provided method and pc into its declaring class' source file and line number. + void TranslateLocation(const mirror::AbstractMethod* method, uint32_t pc, + const char*& source_file, uint32_t& line_number) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + static bool (*is_sensitive_thread_hook_)(); + static uint32_t lock_profiling_threshold_; + + Mutex monitor_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + + // Which thread currently owns the lock? + Thread* volatile owner_; + + // Owner's recursive lock depth. + int lock_count_ GUARDED_BY(monitor_lock_); + + // What object are we part of (for debugging). + mirror::Object* const obj_; + + // Threads currently waiting on this monitor. + Thread* wait_set_ GUARDED_BY(monitor_lock_); + + // Method and dex pc where the lock owner acquired the lock, used when lock + // sampling is enabled. locking_method_ may be null if the lock is currently + // unlocked, or if the lock is acquired by the system when the stack is empty. + const mirror::AbstractMethod* locking_method_ GUARDED_BY(monitor_lock_); + uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_); + + friend class MonitorInfo; + friend class MonitorList; + friend class mirror::Object; + DISALLOW_COPY_AND_ASSIGN(Monitor); +}; + +class MonitorList { + public: + MonitorList(); + ~MonitorList(); + + void Add(Monitor* m); + + void SweepMonitorList(IsMarkedTester is_marked, void* arg) + SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + + private: + Mutex monitor_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + std::list<Monitor*> list_ GUARDED_BY(monitor_list_lock_); + + DISALLOW_COPY_AND_ASSIGN(MonitorList); +}; + +// Collects information about the current state of an object's monitor. +// This is very unsafe, and must only be called when all threads are suspended. +// For use only by the JDWP implementation. +class MonitorInfo { + public: + MonitorInfo(mirror::Object* o) EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); + + Thread* owner; + size_t entry_count; + std::vector<Thread*> waiters; + + private: + DISALLOW_COPY_AND_ASSIGN(MonitorInfo); +}; + +} // namespace art + +#endif // ART_SRC_MONITOR_H_ |