OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/shared_impl/proxy_lock.h" | 5 #include "ppapi/shared_impl/proxy_lock.h" |
6 | 6 |
7 #include "base/synchronization/lock.h" | 7 #include "base/synchronization/lock.h" |
8 #include "ppapi/shared_impl/ppapi_globals.h" | 8 #include "ppapi/shared_impl/ppapi_globals.h" |
9 | 9 |
10 namespace ppapi { | 10 namespace ppapi { |
11 | 11 |
12 // Simple single-thread deadlock detector for the proxy lock. | |
13 // |own_lock| protects |owned_by_thread| and |owning_thread_id|. | |
14 // |owning_thread_id| is the thread owning the proxy lock, and is only | |
15 // valid when |owned_by_thread| is true. | |
16 base::Lock own_lock; | |
brettw
2012/11/29 23:44:33
Can we just use TLS to hold a bool? I think this w
Scott Hess - ex-Googler
2012/11/30 00:49:51
I think this must be why you get paid the big buck
| |
17 bool owned_by_thread = false; | |
18 base::PlatformThreadId owning_thread_id; | |
19 | |
12 // static | 20 // static |
13 void ProxyLock::Acquire() { | 21 void ProxyLock::Acquire() { |
14 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); | 22 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); |
15 if (lock) | 23 |
24 // The lock is unheld, or another thread holds it. | |
25 if (lock) { | |
26 base::AutoLock pin(own_lock); | |
27 bool deadlock = owned_by_thread && | |
28 owning_thread_id == base::PlatformThread::CurrentId(); | |
29 CHECK(!deadlock); | |
30 } | |
31 | |
32 if (lock) { | |
16 lock->Acquire(); | 33 lock->Acquire(); |
34 | |
35 base::AutoLock pin(own_lock); | |
36 CHECK(!owned_by_thread); | |
37 owned_by_thread = true; | |
38 owning_thread_id = base::PlatformThread::CurrentId(); | |
39 } | |
17 } | 40 } |
18 | 41 |
19 // static | 42 // static |
20 void ProxyLock::Release() { | 43 void ProxyLock::Release() { |
21 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); | 44 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); |
22 if (lock) | 45 |
46 if (lock) { | |
47 base::AutoLock pin(own_lock); | |
48 | |
49 // Current thread still holds the lock. | |
50 CHECK(owned_by_thread); | |
51 CHECK_EQ(owning_thread_id, base::PlatformThread::CurrentId()); | |
52 | |
53 owned_by_thread = false; | |
54 owning_thread_id = static_cast<base::PlatformThreadId>(0); | |
55 | |
23 lock->Release(); | 56 lock->Release(); |
57 } | |
24 } | 58 } |
25 | 59 |
26 // static | 60 // static |
27 void ProxyLock::AssertAcquired() { | 61 void ProxyLock::AssertAcquired() { |
28 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); | 62 base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); |
29 if (lock) | 63 if (lock) { |
64 base::AutoLock pin(own_lock); | |
65 | |
66 // Current thread holds the lock. | |
67 CHECK(owned_by_thread); | |
68 CHECK_EQ(owning_thread_id, base::PlatformThread::CurrentId()); | |
69 | |
30 lock->AssertAcquired(); | 70 lock->AssertAcquired(); |
71 } | |
31 } | 72 } |
32 | 73 |
33 void CallWhileUnlocked(const base::Closure& closure) { | 74 void CallWhileUnlocked(const base::Closure& closure) { |
34 ProxyAutoUnlock lock; | 75 ProxyAutoUnlock lock; |
35 closure.Run(); | 76 closure.Run(); |
36 } | 77 } |
37 | 78 |
38 void CallWhileLocked(const base::Closure& closure) { | 79 void CallWhileLocked(const base::Closure& closure) { |
39 ProxyAutoLock lock; | 80 ProxyAutoLock lock; |
40 closure.Run(); | 81 closure.Run(); |
41 } | 82 } |
42 | 83 |
43 } // namespace ppapi | 84 } // namespace ppapi |
OLD | NEW |