blob: 3df3e2c8419f00a7f994806cb0490c9ee08f58e7 [file] [log] [blame]
/*
* Copyright (C) 2011 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_THREAD_LIST_H_
#define ART_RUNTIME_THREAD_LIST_H_
#include "base/mutex.h"
#include "root_visitor.h"
#include <bitset>
#include <list>
namespace art {
class Closure;
class Thread;
class TimingLogger;
class ThreadList {
public:
static const uint32_t kMaxThreadId = 0xFFFF;
static const uint32_t kInvalidId = 0;
static const uint32_t kMainId = 1;
explicit ThreadList();
~ThreadList();
void DumpForSigQuit(std::ostream& os)
LOCKS_EXCLUDED(Locks::thread_list_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void DumpLocked(std::ostream& os) // For thread suspend timeout dumps.
EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
pid_t GetLockOwner(); // For SignalCatcher.
// Thread suspension support.
void ResumeAll()
UNLOCK_FUNCTION(Locks::mutator_lock_)
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
void Resume(Thread* thread, bool for_debugger = false)
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_);
// Suspends all threads and gets exclusive access to the mutator_lock_.
void SuspendAll()
EXCLUSIVE_LOCK_FUNCTION(Locks::mutator_lock_)
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
// Run a checkpoint on threads, running threads are not suspended but run the checkpoint inside
// of the suspend check. Returns how many checkpoints we should expect to run.
size_t RunCheckpoint(Closure* checkpoint_function);
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
// Suspends all threads
void SuspendAllForDebugger()
LOCKS_EXCLUDED(Locks::mutator_lock_,
Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
void SuspendSelfForDebugger()
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_);
void UndoDebuggerSuspensions()
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
// Iterates over all the threads.
void ForEach(void (*callback)(Thread*, void*), void* context)
EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_);
// Add/remove current thread from list.
void Register(Thread* self)
EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_)
LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_);
void Unregister(Thread* self) LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_);
void VisitRoots(RootVisitor* visitor, void* arg) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void VerifyRoots(VerifyRootVisitor* visitor, void* arg) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Return a copy of the thread list.
std::list<Thread*> GetList() EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_) {
return list_;
}
Thread* FindThreadByThinLockId(uint32_t thin_lock_id);
private:
uint32_t AllocThreadId(Thread* self);
void ReleaseThreadId(Thread* self, uint32_t id) LOCKS_EXCLUDED(allocated_ids_lock_);
bool Contains(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_);
bool Contains(pid_t tid) EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_);
void DumpUnattachedThreads(std::ostream& os)
LOCKS_EXCLUDED(Locks::thread_list_lock_);
void SuspendAllDaemonThreads()
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
void WaitForOtherNonDaemonThreadsToExit()
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
void AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread* ignore2 = NULL)
LOCKS_EXCLUDED(Locks::thread_list_lock_,
Locks::thread_suspend_count_lock_);
mutable Mutex allocated_ids_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
std::bitset<kMaxThreadId> allocated_ids_ GUARDED_BY(allocated_ids_lock_);
// The actual list of all threads.
std::list<Thread*> list_ GUARDED_BY(Locks::thread_list_lock_);
// Ongoing suspend all requests, used to ensure threads added to list_ respect SuspendAll.
int suspend_all_count_ GUARDED_BY(Locks::thread_suspend_count_lock_);
int debug_suspend_all_count_ GUARDED_BY(Locks::thread_suspend_count_lock_);
// Signaled when threads terminate. Used to determine when all non-daemons have terminated.
ConditionVariable thread_exit_cond_ GUARDED_BY(Locks::thread_list_lock_);
friend class Thread;
DISALLOW_COPY_AND_ASSIGN(ThreadList);
};
} // namespace art
#endif // ART_RUNTIME_THREAD_LIST_H_