12c43cff01d1271be451671567955158629b23670Christopher Ferris/* 22c43cff01d1271be451671567955158629b23670Christopher Ferris * Copyright (C) 2015 The Android Open Source Project 32c43cff01d1271be451671567955158629b23670Christopher Ferris * 42c43cff01d1271be451671567955158629b23670Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 52c43cff01d1271be451671567955158629b23670Christopher Ferris * you may not use this file except in compliance with the License. 62c43cff01d1271be451671567955158629b23670Christopher Ferris * You may obtain a copy of the License at 72c43cff01d1271be451671567955158629b23670Christopher Ferris * 82c43cff01d1271be451671567955158629b23670Christopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 92c43cff01d1271be451671567955158629b23670Christopher Ferris * 102c43cff01d1271be451671567955158629b23670Christopher Ferris * Unless required by applicable law or agreed to in writing, software 112c43cff01d1271be451671567955158629b23670Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 122c43cff01d1271be451671567955158629b23670Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132c43cff01d1271be451671567955158629b23670Christopher Ferris * See the License for the specific language governing permissions and 142c43cff01d1271be451671567955158629b23670Christopher Ferris * limitations under the License. 152c43cff01d1271be451671567955158629b23670Christopher Ferris */ 162c43cff01d1271be451671567955158629b23670Christopher Ferris 172c43cff01d1271be451671567955158629b23670Christopher Ferris#include <pthread.h> 182c43cff01d1271be451671567955158629b23670Christopher Ferris#include <stdint.h> 192c43cff01d1271be451671567955158629b23670Christopher Ferris#include <string.h> 202c43cff01d1271be451671567955158629b23670Christopher Ferris#include <sys/types.h> 212c43cff01d1271be451671567955158629b23670Christopher Ferris#include <time.h> 222c43cff01d1271be451671567955158629b23670Christopher Ferris#include <ucontext.h> 232c43cff01d1271be451671567955158629b23670Christopher Ferris 242c43cff01d1271be451671567955158629b23670Christopher Ferris#include "BacktraceLog.h" 252c43cff01d1271be451671567955158629b23670Christopher Ferris#include "ThreadEntry.h" 262c43cff01d1271be451671567955158629b23670Christopher Ferris 272c43cff01d1271be451671567955158629b23670Christopher Ferris// Initialize static member variables. 282c43cff01d1271be451671567955158629b23670Christopher FerrisThreadEntry* ThreadEntry::list_ = nullptr; 292c43cff01d1271be451671567955158629b23670Christopher Ferrispthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER; 302c43cff01d1271be451671567955158629b23670Christopher Ferris 312c43cff01d1271be451671567955158629b23670Christopher Ferris// Assumes that ThreadEntry::list_mutex_ has already been locked before 322c43cff01d1271be451671567955158629b23670Christopher Ferris// creating a ThreadEntry object. 332c43cff01d1271be451671567955158629b23670Christopher FerrisThreadEntry::ThreadEntry(pid_t pid, pid_t tid) 342c43cff01d1271be451671567955158629b23670Christopher Ferris : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER), 352c43cff01d1271be451671567955158629b23670Christopher Ferris wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0), 362c43cff01d1271be451671567955158629b23670Christopher Ferris next_(ThreadEntry::list_), prev_(nullptr) { 372c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_condattr_t attr; 382c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_condattr_init(&attr); 392c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 402c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_cond_init(&wait_cond_, &attr); 412c43cff01d1271be451671567955158629b23670Christopher Ferris 422c43cff01d1271be451671567955158629b23670Christopher Ferris // Add ourselves to the list. 432c43cff01d1271be451671567955158629b23670Christopher Ferris if (ThreadEntry::list_) { 442c43cff01d1271be451671567955158629b23670Christopher Ferris ThreadEntry::list_->prev_ = this; 452c43cff01d1271be451671567955158629b23670Christopher Ferris } 462c43cff01d1271be451671567955158629b23670Christopher Ferris ThreadEntry::list_ = this; 472c43cff01d1271be451671567955158629b23670Christopher Ferris} 482c43cff01d1271be451671567955158629b23670Christopher Ferris 492c43cff01d1271be451671567955158629b23670Christopher FerrisThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) { 502c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_lock(&ThreadEntry::list_mutex_); 512c43cff01d1271be451671567955158629b23670Christopher Ferris ThreadEntry* entry = list_; 522c43cff01d1271be451671567955158629b23670Christopher Ferris while (entry != nullptr) { 532c43cff01d1271be451671567955158629b23670Christopher Ferris if (entry->Match(pid, tid)) { 542c43cff01d1271be451671567955158629b23670Christopher Ferris break; 552c43cff01d1271be451671567955158629b23670Christopher Ferris } 562c43cff01d1271be451671567955158629b23670Christopher Ferris entry = entry->next_; 572c43cff01d1271be451671567955158629b23670Christopher Ferris } 582c43cff01d1271be451671567955158629b23670Christopher Ferris 592c43cff01d1271be451671567955158629b23670Christopher Ferris if (!entry) { 602c43cff01d1271be451671567955158629b23670Christopher Ferris if (create) { 612c43cff01d1271be451671567955158629b23670Christopher Ferris entry = new ThreadEntry(pid, tid); 622c43cff01d1271be451671567955158629b23670Christopher Ferris } 632c43cff01d1271be451671567955158629b23670Christopher Ferris } else { 642c43cff01d1271be451671567955158629b23670Christopher Ferris entry->ref_count_++; 652c43cff01d1271be451671567955158629b23670Christopher Ferris } 662c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_unlock(&ThreadEntry::list_mutex_); 672c43cff01d1271be451671567955158629b23670Christopher Ferris 682c43cff01d1271be451671567955158629b23670Christopher Ferris return entry; 692c43cff01d1271be451671567955158629b23670Christopher Ferris} 702c43cff01d1271be451671567955158629b23670Christopher Ferris 712c43cff01d1271be451671567955158629b23670Christopher Ferrisvoid ThreadEntry::Remove(ThreadEntry* entry) { 722d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris entry->Unlock(); 732c43cff01d1271be451671567955158629b23670Christopher Ferris 742c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_lock(&ThreadEntry::list_mutex_); 752c43cff01d1271be451671567955158629b23670Christopher Ferris if (--entry->ref_count_ == 0) { 762c43cff01d1271be451671567955158629b23670Christopher Ferris delete entry; 772c43cff01d1271be451671567955158629b23670Christopher Ferris } 782c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_unlock(&ThreadEntry::list_mutex_); 792c43cff01d1271be451671567955158629b23670Christopher Ferris} 802c43cff01d1271be451671567955158629b23670Christopher Ferris 812c43cff01d1271be451671567955158629b23670Christopher Ferris// Assumes that ThreadEntry::list_mutex_ has already been locked before 822c43cff01d1271be451671567955158629b23670Christopher Ferris// deleting a ThreadEntry object. 832c43cff01d1271be451671567955158629b23670Christopher FerrisThreadEntry::~ThreadEntry() { 842c43cff01d1271be451671567955158629b23670Christopher Ferris if (list_ == this) { 852c43cff01d1271be451671567955158629b23670Christopher Ferris list_ = next_; 862c43cff01d1271be451671567955158629b23670Christopher Ferris } else { 872c43cff01d1271be451671567955158629b23670Christopher Ferris if (next_) { 882c43cff01d1271be451671567955158629b23670Christopher Ferris next_->prev_ = prev_; 892c43cff01d1271be451671567955158629b23670Christopher Ferris } 902c43cff01d1271be451671567955158629b23670Christopher Ferris prev_->next_ = next_; 912c43cff01d1271be451671567955158629b23670Christopher Ferris } 922c43cff01d1271be451671567955158629b23670Christopher Ferris 932c43cff01d1271be451671567955158629b23670Christopher Ferris next_ = nullptr; 942c43cff01d1271be451671567955158629b23670Christopher Ferris prev_ = nullptr; 952c43cff01d1271be451671567955158629b23670Christopher Ferris 962c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_cond_destroy(&wait_cond_); 972c43cff01d1271be451671567955158629b23670Christopher Ferris} 982c43cff01d1271be451671567955158629b23670Christopher Ferris 992d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferrisbool ThreadEntry::Wait(int value) { 1002c43cff01d1271be451671567955158629b23670Christopher Ferris timespec ts; 1012c43cff01d1271be451671567955158629b23670Christopher Ferris clock_gettime(CLOCK_MONOTONIC, &ts); 1022d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris ts.tv_sec += 5; 1032c43cff01d1271be451671567955158629b23670Christopher Ferris 1042d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris bool wait_completed = true; 1052c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_lock(&wait_mutex_); 1062c43cff01d1271be451671567955158629b23670Christopher Ferris while (wait_value_ != value) { 1072c43cff01d1271be451671567955158629b23670Christopher Ferris int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); 1082c43cff01d1271be451671567955158629b23670Christopher Ferris if (ret != 0) { 1092d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); 1102d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris wait_completed = false; 1112c43cff01d1271be451671567955158629b23670Christopher Ferris break; 1122c43cff01d1271be451671567955158629b23670Christopher Ferris } 1132c43cff01d1271be451671567955158629b23670Christopher Ferris } 1142c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_unlock(&wait_mutex_); 1152d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris 1162d09171758b7d98c77f27e439a4caf35dd84c311Christopher Ferris return wait_completed; 1172c43cff01d1271be451671567955158629b23670Christopher Ferris} 1182c43cff01d1271be451671567955158629b23670Christopher Ferris 1192c43cff01d1271be451671567955158629b23670Christopher Ferrisvoid ThreadEntry::Wake() { 1202c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_lock(&wait_mutex_); 1212c43cff01d1271be451671567955158629b23670Christopher Ferris wait_value_++; 1222c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_mutex_unlock(&wait_mutex_); 1232c43cff01d1271be451671567955158629b23670Christopher Ferris 1242c43cff01d1271be451671567955158629b23670Christopher Ferris pthread_cond_signal(&wait_cond_); 1252c43cff01d1271be451671567955158629b23670Christopher Ferris} 1262c43cff01d1271be451671567955158629b23670Christopher Ferris 1272c43cff01d1271be451671567955158629b23670Christopher Ferrisvoid ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) { 1282c43cff01d1271be451671567955158629b23670Christopher Ferris ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(sigcontext); 1292c43cff01d1271be451671567955158629b23670Christopher Ferris // The only thing the unwinder cares about is the mcontext data. 1302c43cff01d1271be451671567955158629b23670Christopher Ferris memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext)); 1312c43cff01d1271be451671567955158629b23670Christopher Ferris} 132