webrtc::Mutex: Introduce mutex_race_check.h.

This change introduces a race-checking mutex implementation useful
for downstream consumers that can guarantee that they invoke
WebRTC serially.

Fixed: webrtc:11787
Change-Id: I7cb74e2e88dc87b751130504c267ac20ee8df4ba
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/179284
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33769}
diff --git a/rtc_base/logging.cc b/rtc_base/logging.cc
index 13a5f02..a333d83 100644
--- a/rtc_base/logging.cc
+++ b/rtc_base/logging.cc
@@ -51,6 +51,17 @@
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/time_utils.h"
 
+#if defined(WEBRTC_RACE_CHECK_MUTEX)
+#if defined(WEBRTC_ABSL_MUTEX)
+#error Please only define one of WEBRTC_RACE_CHECK_MUTEX and WEBRTC_ABSL_MUTEX.
+#endif
+#include "absl/base/const_init.h"
+#include "absl/synchronization/mutex.h"  // nogncheck
+using LoggingMutexLock = ::absl::MutexLock;
+#else
+using LoggingMutexLock = ::webrtc::MutexLock;
+#endif  // if defined(WEBRTC_RACE_CHECK_MUTEX)
+
 namespace rtc {
 namespace {
 // By default, release builds don't log, debug builds at info level
@@ -75,7 +86,15 @@
 // Global lock for log subsystem, only needed to serialize access to streams_.
 // TODO(bugs.webrtc.org/11665): this is not currently constant initialized and
 // trivially destructible.
+#if defined(WEBRTC_RACE_CHECK_MUTEX)
+// When WEBRTC_RACE_CHECK_MUTEX is defined, even though WebRTC objects are
+// invoked serially, the logging is static, invoked concurrently and hence needs
+// protection.
+absl::Mutex g_log_mutex_(absl::kConstInit);
+#else
 webrtc::Mutex g_log_mutex_;
+#endif
+
 }  // namespace
 
 /////////////////////////////////////////////////////////////////////////////
@@ -201,7 +220,7 @@
 #endif
   }
 
-  webrtc::MutexLock lock(&g_log_mutex_);
+  LoggingMutexLock lock(&g_log_mutex_);
   for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
     if (severity_ >= entry->min_severity_) {
 #if defined(WEBRTC_ANDROID)
@@ -250,7 +269,7 @@
 
 void LogMessage::LogToDebug(LoggingSeverity min_sev) {
   g_dbg_sev = min_sev;
-  webrtc::MutexLock lock(&g_log_mutex_);
+  LoggingMutexLock lock(&g_log_mutex_);
   UpdateMinLogSeverity();
 }
 
@@ -259,7 +278,7 @@
 }
 
 int LogMessage::GetLogToStream(LogSink* stream) {
-  webrtc::MutexLock lock(&g_log_mutex_);
+  LoggingMutexLock lock(&g_log_mutex_);
   LoggingSeverity sev = LS_NONE;
   for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
     if (stream == nullptr || stream == entry) {
@@ -270,7 +289,7 @@
 }
 
 void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
-  webrtc::MutexLock lock(&g_log_mutex_);
+  LoggingMutexLock lock(&g_log_mutex_);
   stream->min_severity_ = min_sev;
   stream->next_ = streams_;
   streams_ = stream;
@@ -279,7 +298,7 @@
 }
 
 void LogMessage::RemoveLogToStream(LogSink* stream) {
-  webrtc::MutexLock lock(&g_log_mutex_);
+  LoggingMutexLock lock(&g_log_mutex_);
   for (LogSink** entry = &streams_; *entry != nullptr;
        entry = &(*entry)->next_) {
     if (*entry == stream) {