Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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_ */