tools/profiler/platform.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 // Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
     2 //
     3 // Redistribution and use in source and binary forms, with or without
     4 // modification, are permitted provided that the following conditions
     5 // are met:
     6 //  * Redistributions of source code must retain the above copyright
     7 //    notice, this list of conditions and the following disclaimer.
     8 //  * Redistributions in binary form must reproduce the above copyright
     9 //    notice, this list of conditions and the following disclaimer in
    10 //    the documentation and/or other materials provided with the
    11 //    distribution.
    12 //  * Neither the name of Google, Inc. nor the names of its contributors
    13 //    may be used to endorse or promote products derived from this
    14 //    software without specific prior written permission.
    15 // 
    16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
    19 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    20 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
    21 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    22 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
    23 // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
    24 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    25 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    26 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    27 // SUCH DAMAGE.
    29 #ifndef TOOLS_PLATFORM_H_
    30 #define TOOLS_PLATFORM_H_
    32 #ifdef ANDROID
    33 #include <android/log.h>
    34 #else
    35 #define __android_log_print(a, ...)
    36 #endif
    38 #ifdef XP_UNIX
    39 #include <pthread.h>
    40 #endif
    42 #include <stdint.h>
    43 #include <math.h>
    44 #include "mozilla/unused.h"
    45 #include "mozilla/TimeStamp.h"
    46 #include "mozilla/Mutex.h"
    47 #include "MainThreadUtils.h"
    48 #include "PlatformMacros.h"
    49 #include "v8-support.h"
    50 #include <vector>
    52 #ifdef XP_WIN
    53 #include <windows.h>
    54 #endif
    56 #define ASSERT(a) MOZ_ASSERT(a)
    58 bool moz_profiler_verbose();
    60 #ifdef ANDROID
    61 # if defined(__arm__) || defined(__thumb__)
    62 #  define ENABLE_SPS_LEAF_DATA
    63 #  define ENABLE_ARM_LR_SAVING
    64 # endif
    65 # define LOG(text) \
    66     do { if (moz_profiler_verbose()) \
    67            __android_log_write(ANDROID_LOG_ERROR, "Profiler", text); \
    68     } while (0)
    69 # define LOGF(format, ...) \
    70     do { if (moz_profiler_verbose()) \
    71            __android_log_print(ANDROID_LOG_ERROR, "Profiler", format, \
    72                                __VA_ARGS__); \
    73     } while (0)
    75 #else
    76 # define LOG(text) \
    77     do { if (moz_profiler_verbose()) fprintf(stderr, "Profiler: %s\n", text); \
    78     } while (0)
    79 # define LOGF(format, ...) \
    80     do { if (moz_profiler_verbose()) fprintf(stderr, "Profiler: " format \
    81                                              "\n", __VA_ARGS__);        \
    82     } while (0)
    84 #endif
    86 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_LINUX)
    87 #define ENABLE_SPS_LEAF_DATA
    88 #endif
    90 extern mozilla::TimeStamp sStartTime;
    92 typedef uint8_t* Address;
    94 // ----------------------------------------------------------------------------
    95 // Mutex
    96 //
    97 // Mutexes are used for serializing access to non-reentrant sections of code.
    98 // The implementations of mutex should allow for nested/recursive locking.
   100 class Mutex {
   101  public:
   102   virtual ~Mutex() {}
   104   // Locks the given mutex. If the mutex is currently unlocked, it becomes
   105   // locked and owned by the calling thread, and immediately. If the mutex
   106   // is already locked by another thread, suspends the calling thread until
   107   // the mutex is unlocked.
   108   virtual int Lock() = 0;
   110   // Unlocks the given mutex. The mutex is assumed to be locked and owned by
   111   // the calling thread on entrance.
   112   virtual int Unlock() = 0;
   114   // Tries to lock the given mutex. Returns whether the mutex was
   115   // successfully locked.
   116   virtual bool TryLock() = 0;
   117 };
   119 // ----------------------------------------------------------------------------
   120 // OS
   121 //
   122 // This class has static methods for the different platform specific
   123 // functions. Add methods here to cope with differences between the
   124 // supported platforms.
   126 class OS {
   127  public:
   129   // Sleep for a number of milliseconds.
   130   static void Sleep(const int milliseconds);
   132   // Sleep for a number of microseconds.
   133   static void SleepMicro(const int microseconds);
   135   // Called on startup to initialize platform specific things
   136   static void Startup();
   138  private:
   139   static const int msPerSecond = 1000;
   141 };
   146 // ----------------------------------------------------------------------------
   147 // Thread
   148 //
   149 // Thread objects are used for creating and running threads. When the start()
   150 // method is called the new thread starts running the run() method in the new
   151 // thread. The Thread object should not be deallocated before the thread has
   152 // terminated.
   154 class Thread {
   155  public:
   156   // Create new thread.
   157   explicit Thread(const char* name);
   158   virtual ~Thread();
   160   // Start new thread by calling the Run() method in the new thread.
   161   void Start();
   163   void Join();
   165   inline const char* name() const {
   166     return name_;
   167   }
   169   // Abstract method for run handler.
   170   virtual void Run() = 0;
   172   // The thread name length is limited to 16 based on Linux's implementation of
   173   // prctl().
   174   static const int kMaxThreadNameLength = 16;
   176 #ifdef XP_WIN
   177   HANDLE thread_;
   178   typedef DWORD tid_t;
   179   tid_t thread_id_;
   180 #else
   181   typedef ::pid_t tid_t;
   182 #endif
   183 #if defined(XP_MACOSX)
   184   pthread_t thread_;
   185 #endif
   187   static tid_t GetCurrentId();
   189  private:
   190   void set_name(const char *name);
   192   char name_[kMaxThreadNameLength];
   193   int stack_size_;
   195   DISALLOW_COPY_AND_ASSIGN(Thread);
   196 };
   198 // ----------------------------------------------------------------------------
   199 // HAVE_NATIVE_UNWIND
   200 //
   201 // Pseudo backtraces are available on all platforms.  Native
   202 // backtraces are available only on selected platforms.  Breakpad is
   203 // the only supported native unwinder.  HAVE_NATIVE_UNWIND is set at
   204 // build time to indicate whether native unwinding is possible on this
   205 // platform.  The actual unwind mode currently in use is stored in
   206 // sUnwindMode.
   208 #undef HAVE_NATIVE_UNWIND
   209 #if defined(MOZ_PROFILING) \
   210     && (defined(SPS_PLAT_amd64_linux) || defined(SPS_PLAT_arm_android) \
   211         || defined(SPS_PLAT_x86_linux) \
   212         || defined(SPS_OS_windows) \
   213         || defined(SPS_OS_darwin))
   214 # define HAVE_NATIVE_UNWIND
   215 #endif
   217 /* Some values extracted at startup from environment variables, that
   218    control the behaviour of the breakpad unwinder. */
   219 extern const char* PROFILER_MODE;
   220 extern const char* PROFILER_INTERVAL;
   221 extern const char* PROFILER_ENTRIES;
   222 extern const char* PROFILER_STACK;
   223 extern const char* PROFILER_FEATURES;
   225 void read_profiler_env_vars();
   226 void profiler_usage();
   228 // Helper methods to expose modifying profiler behavior
   229 bool set_profiler_mode(const char*);
   230 bool set_profiler_interval(const char*);
   231 bool set_profiler_entries(const char*);
   232 bool set_profiler_scan(const char*);
   233 bool is_native_unwinding_avail();
   235 typedef  enum { UnwINVALID, UnwNATIVE, UnwPSEUDO, UnwCOMBINED }  UnwMode;
   236 extern UnwMode sUnwindMode;       /* what mode? */
   237 extern int     sUnwindInterval;   /* in milliseconds */
   238 extern int     sUnwindStackScan;  /* max # of dubious frames allowed */
   240 extern int     sProfileEntries;   /* how many entries do we store? */
   242 void set_tls_stack_top(void* stackTop);
   244 // ----------------------------------------------------------------------------
   245 // Sampler
   246 //
   247 // A sampler periodically samples the state of the VM and optionally
   248 // (if used for profiling) the program counter and stack pointer for
   249 // the thread that created it.
   251 class PseudoStack;
   252 class ThreadProfile;
   254 // TickSample captures the information collected for each sample.
   255 class TickSample {
   256  public:
   257   TickSample()
   258       :
   259         pc(NULL),
   260         sp(NULL),
   261         fp(NULL),
   262 #ifdef ENABLE_ARM_LR_SAVING
   263         lr(NULL),
   264 #endif
   265         context(NULL),
   266         isSamplingCurrentThread(false) {}
   268   void PopulateContext(void* aContext);
   270   Address pc;  // Instruction pointer.
   271   Address sp;  // Stack pointer.
   272   Address fp;  // Frame pointer.
   273 #ifdef ENABLE_ARM_LR_SAVING
   274   Address lr;  // ARM link register
   275 #endif
   276   void*   context;   // The context from the signal handler, if available. On
   277                      // Win32 this may contain the windows thread context.
   278   bool    isSamplingCurrentThread;
   279   ThreadProfile* threadProfile;
   280   mozilla::TimeStamp timestamp;
   281 };
   283 class ThreadInfo;
   284 class PlatformData;
   285 class TableTicker;
   286 class SyncProfile;
   287 class Sampler {
   288  public:
   289   // Initialize sampler.
   290   explicit Sampler(double interval, bool profiling, int entrySize);
   291   virtual ~Sampler();
   293   double interval() const { return interval_; }
   295   // This method is called for each sampling period with the current
   296   // program counter.
   297   virtual void Tick(TickSample* sample) = 0;
   299   // Immediately captures the calling thread's call stack and returns it.
   300   virtual SyncProfile* GetBacktrace() = 0;
   302   // Request a save from a signal handler
   303   virtual void RequestSave() = 0;
   304   // Process any outstanding request outside a signal handler.
   305   virtual void HandleSaveRequest() = 0;
   307   // Start and stop sampler.
   308   void Start();
   309   void Stop();
   311   // Is the sampler used for profiling?
   312   bool IsProfiling() const { return profiling_; }
   314   // Whether the sampler is running (that is, consumes resources).
   315   bool IsActive() const { return active_; }
   317   // Low overhead way to stop the sampler from ticking
   318   bool IsPaused() const { return paused_; }
   319   void SetPaused(bool value) { NoBarrier_Store(&paused_, value); }
   321   virtual bool ProfileThreads() const = 0;
   323   int EntrySize() { return entrySize_; }
   325   // We can't new/delete the type safely without defining it
   326   // (-Wdelete-incomplete). Use these Alloc/Free functions instead.
   327   static PlatformData* AllocPlatformData(int aThreadId);
   328   static void FreePlatformData(PlatformData*);
   330   // If we move the backtracing code into the platform files we won't
   331   // need to have these hacks
   332 #ifdef XP_WIN
   333   // xxxehsan sucky hack :(
   334   static uintptr_t GetThreadHandle(PlatformData*);
   335 #endif
   336 #ifdef XP_MACOSX
   337   static pthread_t GetProfiledThread(PlatformData*);
   338 #endif
   340   static std::vector<ThreadInfo*> GetRegisteredThreads() {
   341     return *sRegisteredThreads;
   342   }
   344   static bool RegisterCurrentThread(const char* aName,
   345                                     PseudoStack* aPseudoStack,
   346                                     bool aIsMainThread, void* stackTop);
   347   static void UnregisterCurrentThread();
   349   static void Startup();
   350   // Should only be called on shutdown
   351   static void Shutdown();
   353   static TableTicker* GetActiveSampler() { return sActiveSampler; }
   354   static void SetActiveSampler(TableTicker* sampler) { sActiveSampler = sampler; }
   356   static mozilla::Mutex* sRegisteredThreadsMutex;
   358   static bool CanNotifyObservers() {
   359 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   360     // Android ANR reporter uses the profiler off the main thread
   361     return NS_IsMainThread();
   362 #else
   363     MOZ_ASSERT(NS_IsMainThread());
   364     return true;
   365 #endif
   366   }
   368  protected:
   369   static std::vector<ThreadInfo*>* sRegisteredThreads;
   370   static TableTicker* sActiveSampler;
   372  private:
   373   void SetActive(bool value) { NoBarrier_Store(&active_, value); }
   375   const double interval_;
   376   const bool profiling_;
   377   Atomic32 paused_;
   378   Atomic32 active_;
   379   const int entrySize_;
   381   // Refactor me!
   382 #if defined(SPS_OS_linux) || defined(SPS_OS_android)
   383   bool signal_handler_installed_;
   384   struct sigaction old_sigprof_signal_handler_;
   385   struct sigaction old_sigsave_signal_handler_;
   386   bool signal_sender_launched_;
   387   pthread_t signal_sender_thread_;
   388 #endif
   389 };
   391 class ThreadInfo {
   392  public:
   393   ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop)
   394     : mName(strdup(aName))
   395     , mThreadId(aThreadId)
   396     , mIsMainThread(aIsMainThread)
   397     , mPseudoStack(aPseudoStack)
   398     , mPlatformData(Sampler::AllocPlatformData(aThreadId))
   399     , mProfile(NULL)
   400     , mStackTop(aStackTop) {}
   402   virtual ~ThreadInfo();
   404   const char* Name() const { return mName; }
   405   int ThreadId() const { return mThreadId; }
   407   bool IsMainThread() const { return mIsMainThread; }
   408   PseudoStack* Stack() const { return mPseudoStack; }
   410   void SetProfile(ThreadProfile* aProfile) { mProfile = aProfile; }
   411   ThreadProfile* Profile() const { return mProfile; }
   413   PlatformData* GetPlatformData() const { return mPlatformData; }
   414   void* StackTop() const { return mStackTop; }
   415  private:
   416   char* mName;
   417   int mThreadId;
   418   const bool mIsMainThread;
   419   PseudoStack* mPseudoStack;
   420   PlatformData* mPlatformData;
   421   ThreadProfile* mProfile;
   422   void* const mStackTop;
   423 };
   425 #endif /* ndef TOOLS_PLATFORM_H_ */

mercurial