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 Review URL: https://codereview.chromium.org/1304873011 Cr-Commit-Position: refs/heads/master@{#30489}
This commit is contained in:
parent
70dc24c22f
commit
d6db8e5902
@ -17,6 +17,7 @@
|
||||
#include <ostream>
|
||||
|
||||
#if V8_OS_WIN
|
||||
#include "src/base/atomicops.h"
|
||||
#include "src/base/lazy-instance.h"
|
||||
#include "src/base/win32-headers.h"
|
||||
#endif
|
||||
@ -434,36 +435,35 @@ class HighResolutionTickClock final : public TickClock {
|
||||
|
||||
class RolloverProtectedTickClock final : public TickClock {
|
||||
public:
|
||||
// We initialize rollover_ms_ to 1 to ensure that we will never
|
||||
// return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below.
|
||||
RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
|
||||
RolloverProtectedTickClock() : rollover_(0) {}
|
||||
virtual ~RolloverProtectedTickClock() {}
|
||||
|
||||
int64_t Now() override {
|
||||
LockGuard<Mutex> lock_guard(&mutex_);
|
||||
// We use timeGetTime() to implement TimeTicks::Now(), which rolls over
|
||||
// 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
|
||||
// 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
|
||||
// timeGetTime() provides 1ms granularity when combined with
|
||||
// timeBeginPeriod(). If the host application for V8 wants fast timers, it
|
||||
// can use timeBeginPeriod() to increase the resolution.
|
||||
DWORD now = timeGetTime();
|
||||
if (now < last_seen_now_) {
|
||||
rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days.
|
||||
// We use a lock-free version because the sampler thread calls it
|
||||
// while having the rest of the world stopped, that could cause a deadlock.
|
||||
base::Atomic32 rollover = base::Acquire_Load(&rollover_);
|
||||
base::Atomic32 now = static_cast<base::Atomic32>(timeGetTime());
|
||||
if ((now >> 31) != (rollover & 1)) {
|
||||
base::Release_CompareAndSwap(&rollover_, rollover, rollover + 1);
|
||||
++rollover;
|
||||
}
|
||||
last_seen_now_ = now;
|
||||
return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond;
|
||||
int64_t rollover_ms = static_cast<int64_t>(rollover) << 31;
|
||||
return (rollover_ms | now) * Time::kMicrosecondsPerMillisecond;
|
||||
}
|
||||
|
||||
bool IsHighResolution() override { return false; }
|
||||
|
||||
private:
|
||||
Mutex mutex_;
|
||||
DWORD last_seen_now_;
|
||||
int64_t rollover_ms_;
|
||||
base::Atomic32 rollover_;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user