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