1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/public/cpp/bindings/sync_call_restrictions.h" 6 7 #if ENABLE_SYNC_CALL_RESTRICTIONS 8 9 #include "base/lazy_instance.h" 10 #include "base/logging.h" 11 #include "base/threading/thread_local.h" 12 #include "mojo/public/c/system/core.h" 13 14 namespace mojo { 15 16 namespace { 17 18 class SyncCallSettings { 19 public: 20 static SyncCallSettings* current(); 21 allowed() const22 bool allowed() const { 23 return scoped_allow_count_ > 0 || system_defined_value_; 24 } 25 IncreaseScopedAllowCount()26 void IncreaseScopedAllowCount() { scoped_allow_count_++; } DecreaseScopedAllowCount()27 void DecreaseScopedAllowCount() { 28 DCHECK_LT(0u, scoped_allow_count_); 29 scoped_allow_count_--; 30 } 31 32 private: 33 SyncCallSettings(); 34 ~SyncCallSettings(); 35 36 bool system_defined_value_ = true; 37 size_t scoped_allow_count_ = 0; 38 }; 39 40 base::LazyInstance<base::ThreadLocalPointer<SyncCallSettings>> 41 g_sync_call_settings = LAZY_INSTANCE_INITIALIZER; 42 43 // static current()44SyncCallSettings* SyncCallSettings::current() { 45 SyncCallSettings* result = g_sync_call_settings.Pointer()->Get(); 46 if (!result) { 47 result = new SyncCallSettings(); 48 DCHECK_EQ(result, g_sync_call_settings.Pointer()->Get()); 49 } 50 return result; 51 } 52 SyncCallSettings()53SyncCallSettings::SyncCallSettings() { 54 MojoResult result = MojoGetProperty(MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, 55 &system_defined_value_); 56 DCHECK_EQ(MOJO_RESULT_OK, result); 57 58 DCHECK(!g_sync_call_settings.Pointer()->Get()); 59 g_sync_call_settings.Pointer()->Set(this); 60 } 61 ~SyncCallSettings()62SyncCallSettings::~SyncCallSettings() { 63 g_sync_call_settings.Pointer()->Set(nullptr); 64 } 65 66 } // namespace 67 68 // static AssertSyncCallAllowed()69void SyncCallRestrictions::AssertSyncCallAllowed() { 70 if (!SyncCallSettings::current()->allowed()) { 71 LOG(FATAL) << "Mojo sync calls are not allowed in this process because " 72 << "they can lead to jank and deadlock. If you must make an " 73 << "exception, please see " 74 << "SyncCallRestrictions::ScopedAllowSyncCall and consult " 75 << "mojo/OWNERS."; 76 } 77 } 78 79 // static IncreaseScopedAllowCount()80void SyncCallRestrictions::IncreaseScopedAllowCount() { 81 SyncCallSettings::current()->IncreaseScopedAllowCount(); 82 } 83 84 // static DecreaseScopedAllowCount()85void SyncCallRestrictions::DecreaseScopedAllowCount() { 86 SyncCallSettings::current()->DecreaseScopedAllowCount(); 87 } 88 89 } // namespace mojo 90 91 #endif // ENABLE_SYNC_CALL_RESTRICTIONS 92