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

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: Fixes to cygprofile.cc 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 otpimizations, as this need to be read in re-entrant code.
62 // This variable is NOT accessed from multiple threads (pthread_once guarantees
pasko 2016/04/15 11:42:14 as per offline discussion, this comment needs to b
Primiano Tucci (use gerrit) 2016/04/15 12:51:07 Done.
63 // that).
64 volatile bool g_tls_slot_being_initialized = false;
65
66 // Initializes the global TLS slot. This is invoked only once per process.
67 static void TLSSlotInitializer()
68 {
69 g_tls_slot_being_initialized = true;
70 (void) pthread_key_create(&g_tls_slot, NULL);
pasko 2016/04/15 11:42:14 Everywhere in this file please check return value
Primiano Tucci (use gerrit) 2016/04/15 12:51:07 Went for CHECK. perror doesn't really help on andr
71 g_tls_slot_being_initialized = false;
72 }
55 73
56 // Returns light-weight process ID. On Linux, this is a system-wide unique 74 // Returns light-weight process ID. On Linux, this is a system-wide unique
57 // thread id. 75 // thread id.
58 pid_t GetTID() { 76 pid_t GetTID() {
59 return syscall(__NR_gettid); 77 return syscall(__NR_gettid);
60 } 78 }
61 79
62 timespec GetCurrentTime() { 80 timespec GetCurrentTime() {
63 timespec timestamp; 81 timespec timestamp;
64 clock_gettime(CLOCK_MONOTONIC, &timestamp); 82 clock_gettime(CLOCK_MONOTONIC, &timestamp);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 174
157 ~Thread() { 175 ~Thread() {
158 CHECK_EQ(0, pthread_join(handle_, NULL)); 176 CHECK_EQ(0, pthread_join(handle_, NULL));
159 } 177 }
160 178
161 private: 179 private:
162 static void* EntryPoint(void* data) { 180 static void* EntryPoint(void* data) {
163 // Disable logging on this thread. Although this routine is not instrumented 181 // Disable logging on this thread. Although this routine is not instrumented
164 // (cygprofile.gyp provides that), the called routines are and thus will 182 // (cygprofile.gyp provides that), the called routines are and thus will
165 // call instrumentation. 183 // call instrumentation.
166 CHECK(g_tls_log == NULL); // Must be 0 as this is a new thread. 184 pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
167 g_tls_log = kMagicBeingConstructed; 185 ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
186 pthread_getspecific(g_tls_slot));
187 CHECK(thread_log == NULL); // Must be 0 as this is a new thread.
188 pthread_setspecific(g_tls_slot, kMagicBeingConstructed);
168 189
169 Thread* const instance = reinterpret_cast<Thread*>(data); 190 Thread* const instance = reinterpret_cast<Thread*>(data);
170 instance->thread_callback_.Run(); 191 instance->thread_callback_.Run();
171 return NULL; 192 return NULL;
172 } 193 }
173 194
174 const base::Closure thread_callback_; 195 const base::Closure thread_callback_;
175 pthread_t handle_; 196 pthread_t handle_;
176 197
177 DISALLOW_COPY_AND_ASSIGN(Thread); 198 DISALLOW_COPY_AND_ASSIGN(Thread);
(...skipping 14 matching lines...) Expand all
192 base::Bind(&ThreadLog::FlushInternal, base::Unretained(this))) { 213 base::Bind(&ThreadLog::FlushInternal, base::Unretained(this))) {
193 } 214 }
194 215
195 ThreadLog::ThreadLog(const FlushCallback& flush_callback) 216 ThreadLog::ThreadLog(const FlushCallback& flush_callback)
196 : tid_(GetTID()), 217 : tid_(GetTID()),
197 in_use_(false), 218 in_use_(false),
198 flush_callback_(flush_callback) { 219 flush_callback_(flush_callback) {
199 } 220 }
200 221
201 ThreadLog::~ThreadLog() { 222 ThreadLog::~ThreadLog() {
202 g_tls_log = NULL; 223 pthread_setspecific(g_tls_slot, NULL);
203 } 224 }
204 225
205 void ThreadLog::AddEntry(void* address) { 226 void ThreadLog::AddEntry(void* address) {
206 if (in_use_) 227 if (in_use_)
207 return; 228 return;
208 in_use_ = true; 229 in_use_ = true;
209 230
210 CHECK_EQ(tid_, GetTID()); 231 CHECK_EQ(tid_, GetTID());
211 const std::pair<base::hash_set<void*>::iterator, bool> pair = 232 const std::pair<base::hash_set<void*>::iterator, bool> pair =
212 called_functions_.insert(address); 233 called_functions_.insert(address);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 extern "C" { 372 extern "C" {
352 373
353 // The GCC compiler callbacks, called on every function invocation providing 374 // The GCC compiler callbacks, called on every function invocation providing
354 // addresses of caller and callee codes. 375 // addresses of caller and callee codes.
355 void __cyg_profile_func_enter(void* this_fn, void* call_site) 376 void __cyg_profile_func_enter(void* this_fn, void* call_site)
356 __attribute__((no_instrument_function)); 377 __attribute__((no_instrument_function));
357 void __cyg_profile_func_exit(void* this_fn, void* call_site) 378 void __cyg_profile_func_exit(void* this_fn, void* call_site)
358 __attribute__((no_instrument_function)); 379 __attribute__((no_instrument_function));
359 380
360 void __cyg_profile_func_enter(void* this_fn, void* callee_unused) { 381 void __cyg_profile_func_enter(void* this_fn, void* callee_unused) {
361 if (g_tls_log == NULL) { 382 // Avoid re-entrancy while initializing the TLS slot (once per process).
362 g_tls_log = kMagicBeingConstructed; 383 if (g_tls_slot_being_initialized)
363 ThreadLog* new_log = new ThreadLog(); 384 return;
364 CHECK(new_log); 385
365 g_logs_manager.Pointer()->AddLog(base::WrapUnique(new_log)); 386 pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
366 g_tls_log = new_log; 387 ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
388 pthread_getspecific(g_tls_slot));
389
390 if (thread_log == NULL) {
391 pthread_setspecific(g_tls_slot, kMagicBeingConstructed);
392 thread_log = new ThreadLog();
393 CHECK(thread_log);
394 g_logs_manager.Pointer()->AddLog(base::WrapUnique(thread_log));
395 pthread_setspecific(g_tls_slot, thread_log);
367 } 396 }
368 397
369 if (g_tls_log != kMagicBeingConstructed) 398 if (thread_log != kMagicBeingConstructed)
370 g_tls_log->AddEntry(this_fn); 399 thread_log->AddEntry(this_fn);
371 } 400 }
372 401
373 void __cyg_profile_func_exit(void* this_fn, void* call_site) {} 402 void __cyg_profile_func_exit(void* this_fn, void* call_site) {}
374 403
375 } // extern "C" 404 } // extern "C"
376 } // namespace cygprofile 405 } // 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