Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: tools/cygprofile/cygprofile.cc

Issue 1883093005: Reland (2) of Enable allocator shim for Android (crrev.com/1875043003) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/config/allocator.gni ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/cygprofile/cygprofile.h" 5 #include "tools/cygprofile/cygprofile.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <pthread.h> 8 #include <pthread.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <stdint.h> 10 #include <stdint.h>
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 // "cyglog.PID.LWP.PPID" 45 // "cyglog.PID.LWP.PPID"
46 const char kLogFilenameFormat[] = "%scyglog.%d.%d-%d"; 46 const char kLogFilenameFormat[] = "%scyglog.%d.%d-%d";
47 47
48 // Magic value of above to prevent instrumentation. Used when ThreadLog is being 48 // Magic value of above to prevent instrumentation. Used when ThreadLog is being
49 // constructed (to prevent reentering by malloc, for example) and by the flush 49 // constructed (to prevent reentering by malloc, for example) and by the flush
50 // log thread (to prevent it from being logged0. 50 // log thread (to prevent it from being logged0.
51 ThreadLog* const kMagicBeingConstructed = reinterpret_cast<ThreadLog*>(1); 51 ThreadLog* const kMagicBeingConstructed = reinterpret_cast<ThreadLog*>(1);
52 52
53 // Per-thread pointer to the current log object. 53 // Per-thread pointer to the current log object.
54 static __thread ThreadLog* g_tls_log = NULL; 54 pthread_key_t g_tls_slot;
55
56 // Used to initialize the tls slot, once per the entire process.
57 pthread_once_t g_tls_slot_initializer_once = PTHREAD_ONCE_INIT;
58
59 // This variable is to prevent re-entrancy in the __cyg_profile_func_enter()
60 // while the TLS slot itself is being initialized. Volatile here is required
61 // to avoid compiler optimizations as this need to be read in a re-entrant way.
62 // This variable is written by one thread only, which is the first thread that
63 // happens to run the TLSSlotInitializer(). In practice this will happen very
64 // early in the startup process, as soon as the first instrumented function is
65 // called.
66 volatile bool g_tls_slot_being_initialized = false;
67
68 // Initializes the global TLS slot. This is invoked only once per process.
69 static void TLSSlotInitializer()
70 {
71 g_tls_slot_being_initialized = true;
72 PCHECK(0 == pthread_key_create(&g_tls_slot, NULL));
73 g_tls_slot_being_initialized = false;
74 }
55 75
56 // Returns light-weight process ID. On Linux, this is a system-wide unique 76 // Returns light-weight process ID. On Linux, this is a system-wide unique
57 // thread id. 77 // thread id.
58 pid_t GetTID() { 78 pid_t GetTID() {
59 return syscall(__NR_gettid); 79 return syscall(__NR_gettid);
60 } 80 }
61 81
62 timespec GetCurrentTime() { 82 timespec GetCurrentTime() {
63 timespec timestamp; 83 timespec timestamp;
64 clock_gettime(CLOCK_MONOTONIC, &timestamp); 84 clock_gettime(CLOCK_MONOTONIC, &timestamp);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 164
145 } // namespace 165 } // namespace
146 166
147 // Custom thread implementation that joins on destruction. Note that 167 // Custom thread implementation that joins on destruction. Note that
148 // base::Thread has non-trivial dependencies on e.g. AtExitManager which makes 168 // base::Thread has non-trivial dependencies on e.g. AtExitManager which makes
149 // it hard to use it early. 169 // it hard to use it early.
150 class Thread { 170 class Thread {
151 public: 171 public:
152 Thread(const base::Closure& thread_callback) 172 Thread(const base::Closure& thread_callback)
153 : thread_callback_(thread_callback) { 173 : thread_callback_(thread_callback) {
154 CHECK_EQ(0, pthread_create(&handle_, NULL, &Thread::EntryPoint, this)); 174 PCHECK(0 == pthread_create(&handle_, NULL, &Thread::EntryPoint, this));
155 } 175 }
156 176
157 ~Thread() { 177 ~Thread() {
158 CHECK_EQ(0, pthread_join(handle_, NULL)); 178 PCHECK(0 == pthread_join(handle_, NULL));
159 } 179 }
160 180
161 private: 181 private:
162 static void* EntryPoint(void* data) { 182 static void* EntryPoint(void* data) {
163 // Disable logging on this thread. Although this routine is not instrumented 183 // Disable logging on this thread. Although this routine is not instrumented
164 // (cygprofile.gyp provides that), the called routines are and thus will 184 // (cygprofile.gyp provides that), the called routines are and thus will
165 // call instrumentation. 185 // call instrumentation.
166 CHECK(g_tls_log == NULL); // Must be 0 as this is a new thread. 186 pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
167 g_tls_log = kMagicBeingConstructed; 187 ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
188 pthread_getspecific(g_tls_slot));
189 CHECK(thread_log == NULL); // Must be 0 as this is a new thread.
190 PCHECK(0 == pthread_setspecific(g_tls_slot, kMagicBeingConstructed));
168 191
169 Thread* const instance = reinterpret_cast<Thread*>(data); 192 Thread* const instance = reinterpret_cast<Thread*>(data);
170 instance->thread_callback_.Run(); 193 instance->thread_callback_.Run();
171 return NULL; 194 return NULL;
172 } 195 }
173 196
174 const base::Closure thread_callback_; 197 const base::Closure thread_callback_;
175 pthread_t handle_; 198 pthread_t handle_;
176 199
177 DISALLOW_COPY_AND_ASSIGN(Thread); 200 DISALLOW_COPY_AND_ASSIGN(Thread);
(...skipping 14 matching lines...) Expand all
192 base::Bind(&ThreadLog::FlushInternal, base::Unretained(this))) { 215 base::Bind(&ThreadLog::FlushInternal, base::Unretained(this))) {
193 } 216 }
194 217
195 ThreadLog::ThreadLog(const FlushCallback& flush_callback) 218 ThreadLog::ThreadLog(const FlushCallback& flush_callback)
196 : tid_(GetTID()), 219 : tid_(GetTID()),
197 in_use_(false), 220 in_use_(false),
198 flush_callback_(flush_callback) { 221 flush_callback_(flush_callback) {
199 } 222 }
200 223
201 ThreadLog::~ThreadLog() { 224 ThreadLog::~ThreadLog() {
202 g_tls_log = NULL; 225 PCHECK(0 == pthread_setspecific(g_tls_slot, NULL));
203 } 226 }
204 227
205 void ThreadLog::AddEntry(void* address) { 228 void ThreadLog::AddEntry(void* address) {
206 if (in_use_) 229 if (in_use_)
207 return; 230 return;
208 in_use_ = true; 231 in_use_ = true;
209 232
210 CHECK_EQ(tid_, GetTID()); 233 CHECK_EQ(tid_, GetTID());
211 const std::pair<base::hash_set<void*>::iterator, bool> pair = 234 const std::pair<base::hash_set<void*>::iterator, bool> pair =
212 called_functions_.insert(address); 235 called_functions_.insert(address);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 extern "C" { 374 extern "C" {
352 375
353 // The GCC compiler callbacks, called on every function invocation providing 376 // The GCC compiler callbacks, called on every function invocation providing
354 // addresses of caller and callee codes. 377 // addresses of caller and callee codes.
355 void __cyg_profile_func_enter(void* this_fn, void* call_site) 378 void __cyg_profile_func_enter(void* this_fn, void* call_site)
356 __attribute__((no_instrument_function)); 379 __attribute__((no_instrument_function));
357 void __cyg_profile_func_exit(void* this_fn, void* call_site) 380 void __cyg_profile_func_exit(void* this_fn, void* call_site)
358 __attribute__((no_instrument_function)); 381 __attribute__((no_instrument_function));
359 382
360 void __cyg_profile_func_enter(void* this_fn, void* callee_unused) { 383 void __cyg_profile_func_enter(void* this_fn, void* callee_unused) {
361 if (g_tls_log == NULL) { 384 // Avoid re-entrancy while initializing the TLS slot (once per process).
362 g_tls_log = kMagicBeingConstructed; 385 if (g_tls_slot_being_initialized)
363 ThreadLog* new_log = new ThreadLog(); 386 return;
364 CHECK(new_log); 387
365 g_logs_manager.Pointer()->AddLog(base::WrapUnique(new_log)); 388 pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
366 g_tls_log = new_log; 389 ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
390 pthread_getspecific(g_tls_slot));
391
392 if (thread_log == NULL) {
393 PCHECK(0 == pthread_setspecific(g_tls_slot, kMagicBeingConstructed));
394 thread_log = new ThreadLog();
395 CHECK(thread_log);
396 g_logs_manager.Pointer()->AddLog(base::WrapUnique(thread_log));
397 PCHECK(0 == pthread_setspecific(g_tls_slot, thread_log));
367 } 398 }
368 399
369 if (g_tls_log != kMagicBeingConstructed) 400 if (thread_log != kMagicBeingConstructed)
370 g_tls_log->AddEntry(this_fn); 401 thread_log->AddEntry(this_fn);
371 } 402 }
372 403
373 void __cyg_profile_func_exit(void* this_fn, void* call_site) {} 404 void __cyg_profile_func_exit(void* this_fn, void* call_site) {}
374 405
375 } // extern "C" 406 } // extern "C"
376 } // namespace cygprofile 407 } // namespace cygprofile
OLDNEW
« no previous file with comments | « build/config/allocator.gni ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698