Index: webrtc/base/platform_thread.cc |
diff --git a/webrtc/base/platform_thread.cc b/webrtc/base/platform_thread.cc |
index 52f88106b7cab16f34fc4c3e2b233ba047a1a642..afacfdca2d22c8945fb4274fdfa506f2a7cfad0e 100644 |
--- a/webrtc/base/platform_thread.cc |
+++ b/webrtc/base/platform_thread.cc |
@@ -12,6 +12,7 @@ |
#include "webrtc/base/atomicops.h" |
#include "webrtc/base/checks.h" |
+#include "webrtc/base/timeutils.h" |
#if defined(WEBRTC_LINUX) |
#include <sys/prctl.h> |
@@ -220,25 +221,53 @@ void PlatformThread::Run() { |
run_function_(obj_); |
return; |
} |
-// TODO(tommi): Delete the below. |
-#if !defined(WEBRTC_MAC) && !defined(WEBRTC_WIN) |
- const struct timespec ts_null = {0}; |
+ |
+// TODO(tommi): Delete the rest of this function when looping isn't supported. |
+#if RTC_DCHECK_IS_ON |
+ // These constants control the busy loop detection algorithm below. |
+ // |kMaxLoopCount| controls the limit for how many times we allow the loop |
+ // to run within a period, before DCHECKing. |
+ // |kPeriodToMeasureMs| controls how long that period is. |
+ static const int kMaxLoopCount = 1000; |
+ static const int kPeriodToMeasureMs = 100; |
+ int64_t loop_stamps[kMaxLoopCount] = {}; |
+ int64_t sequence_nr = 0; |
#endif |
+ |
do { |
// The interface contract of Start/Stop is that for a successful call to |
// Start, there should be at least one call to the run function. So we |
// call the function before checking |stop_|. |
if (!run_function_deprecated_(obj_)) |
break; |
+#if RTC_DCHECK_IS_ON |
+ auto id = sequence_nr % kMaxLoopCount; |
+ loop_stamps[id] = rtc::TimeMillis(); |
+ if (sequence_nr > kMaxLoopCount) { |
+ auto compare_id = (id + 1) % kMaxLoopCount; |
+ auto diff = loop_stamps[id] - loop_stamps[compare_id]; |
+ RTC_DCHECK_GE(diff, 0); |
+ if (diff < kPeriodToMeasureMs) { |
+ RTC_NOTREACHED() << "This thread is too busy: " << name_ << " " << diff |
+ << "ms sequence=" << sequence_nr << " " |
+ << loop_stamps[id] << " vs " << loop_stamps[compare_id] |
+ << ", " << id << " vs " << compare_id; |
+ } |
+ } |
+ ++sequence_nr; |
+#endif |
#if defined(WEBRTC_WIN) |
// Alertable sleep to permit RaiseFlag to run and update |stop_|. |
SleepEx(0, true); |
} while (!stop_); |
#else |
-#if defined(WEBRTC_MAC) |
- sched_yield(); |
-#else |
+#if defined(UNDEFINED_SANITIZER) || defined(WEBRTC_ANDROID) |
+ // UBSAN and Android don't like |sched_yield()| that much. |
+ static const struct timespec ts_null = {0}; |
nanosleep(&ts_null, nullptr); |
+#else // !(defined(UNDEFINED_SANITIZER) || defined(WEBRTC_ANDROID)) |
+ // Mac and Linux show better performance with sched_yield. |
+ sched_yield(); |
#endif |
} while (!AtomicOps::AcquireLoad(&stop_flag_)); |
#endif // defined(WEBRTC_WIN) |