Commit 6184f1fe authored by alph's avatar alph Committed by Commit bot

Fix CPU profiler deadlock on Windows + AMD CPU.

Implement a lock free version of RolloverProtectedTickClock::Now
to eliminate a deadlock.

BUG=chromium:521420
LOG=Y

Committed: https://crrev.com/d6db8e5902af1f067f0f149844f4e92824ee93f3
Cr-Commit-Position: refs/heads/master@{#30489}

Review URL: https://codereview.chromium.org/1304873011

Cr-Commit-Position: refs/heads/master@{#30522}
parent 224d74ed
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <ostream> #include <ostream>
#if V8_OS_WIN #if V8_OS_WIN
#include "src/base/atomicops.h"
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
#include "src/base/win32-headers.h" #include "src/base/win32-headers.h"
#endif #endif
...@@ -434,36 +435,35 @@ class HighResolutionTickClock final : public TickClock { ...@@ -434,36 +435,35 @@ class HighResolutionTickClock final : public TickClock {
class RolloverProtectedTickClock final : public TickClock { class RolloverProtectedTickClock final : public TickClock {
public: public:
// We initialize rollover_ms_ to 1 to ensure that we will never RolloverProtectedTickClock() : rollover_(0) {}
// return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below.
RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
virtual ~RolloverProtectedTickClock() {} virtual ~RolloverProtectedTickClock() {}
int64_t Now() override { int64_t Now() override {
LockGuard<Mutex> lock_guard(&mutex_);
// We use timeGetTime() to implement TimeTicks::Now(), which rolls over // We use timeGetTime() to implement TimeTicks::Now(), which rolls over
// every ~49.7 days. We try to track rollover ourselves, which works if // every ~49.7 days. We try to track rollover ourselves, which works if
// TimeTicks::Now() is called at least every 49 days. // TimeTicks::Now() is called at least every 24 days.
// Note that we do not use GetTickCount() here, since timeGetTime() gives // Note that we do not use GetTickCount() here, since timeGetTime() gives
// more predictable delta values, as described here: // more predictable delta values, as described here:
// http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx
// timeGetTime() provides 1ms granularity when combined with // timeGetTime() provides 1ms granularity when combined with
// timeBeginPeriod(). If the host application for V8 wants fast timers, it // timeBeginPeriod(). If the host application for V8 wants fast timers, it
// can use timeBeginPeriod() to increase the resolution. // can use timeBeginPeriod() to increase the resolution.
DWORD now = timeGetTime(); // We use a lock-free version because the sampler thread calls it
if (now < last_seen_now_) { // while having the rest of the world stopped, that could cause a deadlock.
rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days. base::Atomic32 rollover = base::Acquire_Load(&rollover_);
uint32_t now = static_cast<uint32_t>(timeGetTime());
if ((now >> 31) != static_cast<uint32_t>(rollover & 1)) {
base::Release_CompareAndSwap(&rollover_, rollover, rollover + 1);
++rollover;
} }
last_seen_now_ = now; uint64_t ms = (static_cast<uint64_t>(rollover) << 31) | now;
return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond; return static_cast<int64_t>(ms * Time::kMicrosecondsPerMillisecond);
} }
bool IsHighResolution() override { return false; } bool IsHighResolution() override { return false; }
private: private:
Mutex mutex_; base::Atomic32 rollover_;
DWORD last_seen_now_;
int64_t rollover_ms_;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment