1 : /*
2 : * Copyright 2008 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 :
8 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_LOCK_H_
9 : #define NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_LOCK_H_
10 :
11 : #include "native_client/src/include/nacl_macros.h"
12 : #include "native_client/src/shared/platform/win/lock_impl.h"
13 :
14 : // A convenient wrapper for a critical section.
15 : //
16 : // NOTE: A thread may acquire the same lock multiple times, but it must call
17 : // Release for each call to Acquire in order to finally release the lock.
18 : //
19 : // Complication: UnitTest for DeathTests catch DCHECK exceptions, so we need
20 : // to write code assuming DCHECK will throw. This means we need to save any
21 : // assertable value in a local until we can safely throw.
22 :
23 : namespace NaCl {
24 :
25 : class Lock {
26 : public:
27 : Lock();
28 : ~Lock();
29 : void Acquire();
30 : void Release();
31 : bool Try();
32 :
33 : private:
34 : NaCl::LockImpl lock_; // User-supplied underlying lock implementation.
35 :
36 : // All private data is implicitly protected by spin_lock_.
37 : // Be VERY careful to only access under that lock.
38 : int32_t recursion_count_shadow_;
39 :
40 : // Allow access to GetCurrentThreadRecursionCount()
41 : friend class AutoUnlock;
42 : int32_t GetCurrentThreadRecursionCount();
43 :
44 : #ifndef NDEBUG
45 : // Even in Debug mode, the expensive tallies won't be calculated by default.
46 : bool recursion_used_;
47 : int32_t acquisition_count_;
48 :
49 : int32_t contention_count_;
50 : #endif // NDEBUG
51 :
52 : NACL_DISALLOW_COPY_AND_ASSIGN(Lock);
53 : };
54 :
55 : // A helper class that acquires the given Lock while the AutoLock is in scope.
56 : class AutoLock {
57 : public:
58 2 : explicit AutoLock(Lock& lock) : lock_(lock) {
59 2 : lock_.Acquire();
60 2 : }
61 :
62 2 : ~AutoLock() {
63 2 : lock_.Release();
64 2 : }
65 :
66 : private:
67 : Lock& lock_;
68 : NACL_DISALLOW_COPY_AND_ASSIGN(AutoLock);
69 : };
70 :
71 : // A helper macro to perform a single operation (expressed by expr)
72 : // in a lock
73 : #define LOCKED_EXPRESSION(lock, expr) \
74 : do { \
75 : NaCl::AutoLock _auto_lock(lock); \
76 : (expr); \
77 : } while (0)
78 :
79 : // AutoUnlock is a helper class for ConditionVariable instances
80 : // that is analogous to AutoLock. It provides for nested Releases
81 : // of a lock for the Wait functionality of a ConditionVariable class.
82 : // The destructor automatically does the corresponding Acquire
83 : // calls (to return to the initial nested lock state).
84 :
85 : // Instances of AutoUnlock can ***ONLY*** validly be constructed if the
86 : // caller currently holds the lock provided as the constructor's argument.
87 : // If that ***REQUIREMENT*** is violated in debug mode, a DCHECK will
88 : // be generated in the Lock class. In production (non-debug),
89 : // the results are undefined (and probably bad) if the caller
90 : // is not already holding the indicated lock.
91 : class ConditionVariable;
92 : class AutoUnlock {
93 : private: // Everything is private, so only our friend can use us.
94 : friend class ConditionVariable; // The only user of this class.
95 : explicit AutoUnlock(Lock& lock);
96 : ~AutoUnlock();
97 :
98 : Lock* lock_;
99 : int release_count_;
100 : };
101 :
102 : } // namespace NaCl
103 :
104 : #endif // NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_WIN_LOCK_H_
|