diff options
Diffstat (limited to 'mojo/public/cpp/bindings/lib/sync_call_restrictions.cc')
-rw-r--r-- | mojo/public/cpp/bindings/lib/sync_call_restrictions.cc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc new file mode 100644 index 0000000000..585a8f094c --- /dev/null +++ b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc @@ -0,0 +1,93 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/bindings/sync_call_restrictions.h" + +#if ENABLE_SYNC_CALL_RESTRICTIONS + +#include "base/debug/leak_annotations.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/threading/thread_local.h" +#include "mojo/public/c/system/core.h" + +namespace mojo { + +namespace { + +class SyncCallSettings { + public: + static SyncCallSettings* current(); + + bool allowed() const { + return scoped_allow_count_ > 0 || system_defined_value_; + } + + void IncreaseScopedAllowCount() { scoped_allow_count_++; } + void DecreaseScopedAllowCount() { + DCHECK_LT(0u, scoped_allow_count_); + scoped_allow_count_--; + } + + private: + SyncCallSettings(); + ~SyncCallSettings(); + + bool system_defined_value_ = true; + size_t scoped_allow_count_ = 0; +}; + +base::LazyInstance<base::ThreadLocalPointer<SyncCallSettings>>::DestructorAtExit + g_sync_call_settings = LAZY_INSTANCE_INITIALIZER; + +// static +SyncCallSettings* SyncCallSettings::current() { + SyncCallSettings* result = g_sync_call_settings.Pointer()->Get(); + if (!result) { + result = new SyncCallSettings(); + ANNOTATE_LEAKING_OBJECT_PTR(result); + DCHECK_EQ(result, g_sync_call_settings.Pointer()->Get()); + } + return result; +} + +SyncCallSettings::SyncCallSettings() { + MojoResult result = MojoGetProperty(MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, + &system_defined_value_); + DCHECK_EQ(MOJO_RESULT_OK, result); + + DCHECK(!g_sync_call_settings.Pointer()->Get()); + g_sync_call_settings.Pointer()->Set(this); +} + +SyncCallSettings::~SyncCallSettings() { + g_sync_call_settings.Pointer()->Set(nullptr); +} + +} // namespace + +// static +void SyncCallRestrictions::AssertSyncCallAllowed() { + if (!SyncCallSettings::current()->allowed()) { + LOG(FATAL) << "Mojo sync calls are not allowed in this process because " + << "they can lead to jank and deadlock. If you must make an " + << "exception, please see " + << "SyncCallRestrictions::ScopedAllowSyncCall and consult " + << "mojo/OWNERS."; + } +} + +// static +void SyncCallRestrictions::IncreaseScopedAllowCount() { + SyncCallSettings::current()->IncreaseScopedAllowCount(); +} + +// static +void SyncCallRestrictions::DecreaseScopedAllowCount() { + SyncCallSettings::current()->DecreaseScopedAllowCount(); +} + +} // namespace mojo + +#endif // ENABLE_SYNC_CALL_RESTRICTIONS |