1 // Copyright (c) 2012 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.
5 #include "ppapi/shared_impl/proxy_lock.h"
7 #include "base/lazy_instance.h"
8 #include "base/synchronization/lock.h"
9 #include "base/threading/thread_local.h"
10 #include "ppapi/shared_impl/ppapi_globals.h"
14 base::LazyInstance
<base::Lock
>::Leaky g_proxy_lock
= LAZY_INSTANCE_INITIALIZER
;
16 bool g_disable_locking
= false;
17 base::LazyInstance
<base::ThreadLocalBoolean
>::Leaky
18 g_disable_locking_for_thread
= LAZY_INSTANCE_INITIALIZER
;
20 // Simple single-thread deadlock detector for the proxy lock.
21 // |true| when the current thread has the lock.
22 base::LazyInstance
<base::ThreadLocalBoolean
>::Leaky g_proxy_locked_on_thread
=
23 LAZY_INSTANCE_INITIALIZER
;
26 base::Lock
* ProxyLock::Get() {
27 if (g_disable_locking
|| g_disable_locking_for_thread
.Get().Get())
29 return &g_proxy_lock
.Get();
32 // Functions below should only access the lock via Get to ensure that they don't
33 // try to use the lock on the host side of the proxy, where locking is
34 // unnecessary and wrong (because we haven't coded the host side to account for
38 void ProxyLock::Acquire() {
39 base::Lock
* lock
= Get();
41 // This thread does not already hold the lock.
42 const bool deadlock
= g_proxy_locked_on_thread
.Get().Get();
46 g_proxy_locked_on_thread
.Get().Set(true);
51 void ProxyLock::Release() {
52 base::Lock
* lock
= Get();
54 // This thread currently holds the lock.
55 const bool locked
= g_proxy_locked_on_thread
.Get().Get();
58 g_proxy_locked_on_thread
.Get().Set(false);
64 void ProxyLock::AssertAcquired() {
65 base::Lock
* lock
= Get();
67 // This thread currently holds the lock.
68 const bool locked
= g_proxy_locked_on_thread
.Get().Get();
71 lock
->AssertAcquired();
76 void ProxyLock::DisableLocking() {
77 // Note, we don't DCHECK that this flag isn't already set, because multiple
78 // unit tests may run in succession and all set it.
79 g_disable_locking
= true;
82 ProxyLock::LockingDisablerForTest::LockingDisablerForTest() {
83 // Note, we don't DCHECK that this flag isn't already set, because multiple
84 // unit tests may run in succession and all set it.
85 g_disable_locking_for_thread
.Get().Set(true);
88 ProxyLock::LockingDisablerForTest::~LockingDisablerForTest() {
89 g_disable_locking_for_thread
.Get().Set(false);
92 void CallWhileUnlocked(const base::Closure
& closure
) {