| 213 | |
| 214 | |
| 215 | void SubmitSpinLockProfileData(const void *contendedlock, int64_t wait_cycles) { |
| 216 | TRACE_COUNTER_INCREMENT("spinlock_wait_cycles", wait_cycles); |
| 217 | bool profiling_enabled = base::subtle::Acquire_Load(&g_profiling_enabled); |
| 218 | bool long_wait_time = wait_cycles > FLAGS_lock_contention_trace_threshold_cycles; |
| 219 | // Short circuit this function quickly in the common case. |
| 220 | if (PREDICT_TRUE(!profiling_enabled && !long_wait_time)) { |
| 221 | return; |
| 222 | } |
| 223 | |
| 224 | static __thread bool in_func = false; |
| 225 | if (in_func) return; // non-re-entrant |
| 226 | in_func = true; |
| 227 | |
| 228 | StackTrace stack; |
| 229 | stack.Collect(); |
| 230 | |
| 231 | if (profiling_enabled) { |
| 232 | DCHECK_NOTNULL(g_contention_stacks)->AddStack(stack, wait_cycles); |
| 233 | } |
| 234 | |
| 235 | if (PREDICT_FALSE(long_wait_time)) { |
| 236 | Trace* t = Trace::CurrentTrace(); |
| 237 | if (t) { |
| 238 | double seconds = static_cast<double>(wait_cycles) / base::CyclesPerSecond(); |
| 239 | char backtrace_buffer[1024]; |
| 240 | stack.StringifyToHex(backtrace_buffer, arraysize(backtrace_buffer)); |
| 241 | TRACE_TO(t, "Waited $0 on lock $1. stack: $2", |
| 242 | HumanReadableElapsedTime::ToShortString(seconds), contendedlock, |
| 243 | backtrace_buffer); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | LongAdder* la = reinterpret_cast<LongAdder*>( |
| 248 | base::subtle::Acquire_Load(reinterpret_cast<AtomicWord*>(&g_contended_cycles))); |
| 249 | if (la) { |
| 250 | la->IncrementBy(wait_cycles); |
| 251 | } |
| 252 | |
| 253 | in_func = false; |
| 254 | } |
| 255 | |
| 256 | void DoInit() { |
| 257 | base::subtle::Release_Store(reinterpret_cast<AtomicWord*>(&g_contention_stacks), |