117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris/*
217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Copyright (C) 2013 The Android Open Source Project
317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris *
417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * you may not use this file except in compliance with the License.
617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * You may obtain a copy of the License at
717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris *
817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris *
1017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * Unless required by applicable law or agreed to in writing, software
1117e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
1217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1317e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * See the License for the specific language governing permissions and
1417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris * limitations under the License.
1517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris */
1617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
1717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#ifndef _LIBBACKTRACE_BACKTRACE_THREAD_H
1817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#define _LIBBACKTRACE_BACKTRACE_THREAD_H
1917e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
2017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <inttypes.h>
21a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <pthread.h>
22aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#include <signal.h>
23a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <string.h>
2417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#include <sys/types.h>
25a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris#include <ucontext.h>
2617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
27df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include "BacktraceImpl.h"
2817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
29aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris// The signal used to cause a thread to dump the stack.
30aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#if defined(__GLIBC__)
31aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris// GLIBC reserves __SIGRTMIN signals, so use SIGRTMIN to avoid errors.
32aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#define THREAD_SIGNAL SIGRTMIN
33aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#else
34aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#define THREAD_SIGNAL (__SIGRTMIN+1)
35aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris#endif
36aa63d9f980f95718fc28ca7e222c1e8d7ca9e778Christopher Ferris
37a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisclass ThreadEntry {
38a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrispublic:
39a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  static ThreadEntry* Get(pid_t pid, pid_t tid, bool create = true);
4017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
41a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  static void Remove(ThreadEntry* entry);
4217e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
43a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  void Wake();
4417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
45a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  void Wait(int);
4617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
47e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris  void CopyUcontextFromSigcontext(void*);
48e48460762273586744a79d146c2916bcfca7e9e4Christopher Ferris
49a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  inline void Lock() {
50a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris    pthread_mutex_lock(&mutex_);
51a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris    // Reset the futex value in case of multiple unwinds of the same thread.
52a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris    futex_ = 0;
53a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  }
5417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
55a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  inline void Unlock() {
56a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris    pthread_mutex_unlock(&mutex_);
57a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  }
5817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
59a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  inline ucontext_t* GetUcontext() { return &ucontext_; }
6017e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
61a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisprivate:
62a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  ThreadEntry(pid_t pid, pid_t tid);
63a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  ~ThreadEntry();
6417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
65a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid_ && chk_tid == tid_); }
6617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
67a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  pid_t pid_;
68a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  pid_t tid_;
69a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  int futex_;
70a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  int ref_count_;
71a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  pthread_mutex_t mutex_;
72a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  ThreadEntry* next_;
73a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  ThreadEntry* prev_;
74a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  ucontext_t ucontext_;
7517e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
76a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  static ThreadEntry* list_;
77a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  static pthread_mutex_t list_mutex_;
78a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris};
79a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris
80a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrisclass BacktraceThread : public BacktraceCurrent {
81a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferrispublic:
82a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  BacktraceThread(BacktraceImpl* impl, pid_t tid, BacktraceMap* map);
83a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  virtual ~BacktraceThread();
8417e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
85a2efd3ac7abe223aa7a8ba8b5ba448216c4953b4Christopher Ferris  virtual bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext);
8617e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris};
8717e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris
8817e91d44edf5e6476a477a200bcd89d4327358a3Christopher Ferris#endif // _LIBBACKTRACE_BACKTRACE_THREAD_H
89