DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_ThreadStackHelper_h
#define mozilla_ThreadStackHelper_h

#include "mozilla/ThreadHangStats.h"
#include "js/ProfilingStack.h"

#include <stddef.h>

#if defined(XP_LINUX)
#include <signal.h>
#include <semaphore.h>
#include <sys/types.h>
#elif defined(XP_WIN)
#include <windows.h>
#elif defined(XP_MACOSX)
#include <mach/mach.h>
#endif

// Support pseudostack on these platforms.
#if defined(XP_LINUX) || defined(XP_WIN) || defined(XP_MACOSX)
#  ifdef MOZ_GECKO_PROFILER
#    define MOZ_THREADSTACKHELPER_PSEUDO
#  endif
#endif

#ifdef MOZ_THREADSTACKHELPER_PSEUDO
#  define MOZ_THREADSTACKHELPER_NATIVE
#  if defined(__i386__) || defined(_M_IX86)
#    define MOZ_THREADSTACKHELPER_X86
#  elif defined(__x86_64__) || defined(_M_X64)
#    define MOZ_THREADSTACKHELPER_X64
#  elif defined(__arm__) || defined(_M_ARM)
#    define MOZ_THREADSTACKHELPER_ARM
#  else
     // Unsupported architecture
#    undef MOZ_THREADSTACKHELPER_NATIVE
#  endif
#endif

namespace mozilla {

/**
 * ThreadStackHelper is used to retrieve the profiler pseudo-stack of a
 * thread, as an alternative of using the profiler to take a profile.
 * The target thread first declares an ThreadStackHelper instance;
 * then another thread can call ThreadStackHelper::GetStack to retrieve
 * the pseudo-stack of the target thread at that instant.
 *
 * Only non-copying labels are included in the stack, which means labels
 * with custom text and markers are not included.
 */
class ThreadStackHelper
{
public:
  typedef Telemetry::HangStack Stack;

private:
  Stack* mStackToFill;
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
  const PseudoStack* const mPseudoStack;
#ifdef MOZ_THREADSTACKHELPER_NATIVE
  class ThreadContext;
  // Set to non-null if GetStack should get the thread context.
  ThreadContext* mContextToFill;
  intptr_t mThreadStackBase;
#endif
  size_t mMaxStackSize;
  size_t mMaxBufferSize;
#endif

  bool PrepareStackBuffer(Stack& aStack);
  void FillStackBuffer();
  void FillThreadContext(void* aContext = nullptr);
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
  const char* AppendJSEntry(const volatile js::ProfileEntry* aEntry,
                            intptr_t& aAvailableBufferSize,
                            const char* aPrevLabel);
#endif
#ifdef MOZ_THREADSTACKHELPER_NATIVE
  void GetThreadStackBase();
#endif

public:
  /**
   * Initialize ThreadStackHelper. Must be called from main thread.
   */
  static void Startup();
  /**
   * Uninitialize ThreadStackHelper. Must be called from main thread.
   */
  static void Shutdown();

  /**
   * Create a ThreadStackHelper instance targeting the current thread.
   */
  ThreadStackHelper();

  ~ThreadStackHelper();

  /**
   * Retrieve the current pseudostack of the thread associated
   * with this ThreadStackHelper.
   *
   * @param aStack Stack instance to be filled.
   */
  void GetStack(Stack& aStack);

  /**
   * Retrieve the current native stack of the thread associated
   * with this ThreadStackHelper.
   *
   * @param aNativeStack Stack instance to be filled.
   */
  void GetNativeStack(Stack& aStack);

#if defined(XP_LINUX)
private:
  static int sInitialized;
  static int sFillStackSignum;

  static void FillStackHandler(int aSignal, siginfo_t* aInfo, void* aContext);

  sem_t mSem;
  pid_t mThreadID;

#elif defined(XP_WIN)
private:
  bool mInitialized;
  HANDLE mThreadID;

#elif defined(XP_MACOSX)
private:
  thread_act_t mThreadID;

#endif
};

} // namespace mozilla

#endif // mozilla_ThreadStackHelper_h