mutex.h revision 25fd14b87cced64a179dee885573113be5e11944
18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/*
28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License.
68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at
78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and
148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License.
158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */
168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#ifndef ART_SRC_MUTEX_H_
188daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#define ART_SRC_MUTEX_H_
198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <pthread.h>
21cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom#include <stdint.h>
22ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
23ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes#include <iosfwd>
248daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <string>
258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h"
278daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "logging.h"
288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "macros.h"
298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3066aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers// Currently Darwin doesn't support locks with timeouts.
3166aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if !defined(__APPLE__)
3266aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 1
3366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#else
3466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 0
3566aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
3666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers
378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3925fd14b87cced64a179dee885573113be5e11944Ian Rogersconst bool kDebugLocking = kIsDebugBuild;
4025fd14b87cced64a179dee885573113be5e11944Ian Rogers
4100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex;
4200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex;
4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
4400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// MutexLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or
4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free
4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// partial ordering and thereby cause deadlock situations to fail checks.
4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163
4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersenum MutexLevel {
5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kLoggingLock = 0,
5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kUnexpectedSignalLock = 1,
52ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes  kThreadSuspendCountLock = 2,
5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kAbortLock = 3,
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kDefaultMutexLevel = 4,
5515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kJdwpSerialLock = 5,
5615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kAllocSpaceLock = 6,
5715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kLoadLibraryLock = 7,
5815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kClassLinkerClassesLock = 8,
5915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kThreadListLock = 9,
6015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kHeapBitmapLock = 10,
6115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kMonitorLock = 11,
6215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kMutatorLock = 12,
6315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  kZygoteCreationLock = 13,
6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  kMaxMutexLevel = kMutatorLock,
65ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes};
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstd::ostream& operator<<(std::ostream& os, const MutexLevel& rhs);
67ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
6800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Global mutexes corresponding to the levels above.
69b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogersclass Locks {
708daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static void Init();
728daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds
7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // a share on the mutator_lock_. The garbage collector may also execute with shared access but
7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // at times requires exclusive access to the heap (not to be confused with the heap meta-data
7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks
7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_
7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector)
8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // chance to acquire the lock.
8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //
8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Thread suspension:
8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Shared users                                  | Exclusive user
8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // (holding mutator lock and in kRunnable state) |   .. running ..
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               | Request thread suspension by:
8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - acquiring thread_suspend_count_lock_
8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - incrementing Thread::suspend_count_ on
9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |     all mutator threads
9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               |   - releasing thread_suspend_count_lock_
9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. running ..                               | Block trying to acquire exclusive mutator lock
9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Poll Thread::suspend_count_ and enter full    |   .. blocked ..
9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // suspend code.                                 |   .. blocked ..
9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Change state to kSuspended                    |   .. blocked ..
9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // x: Release share on mutator_lock_             | Carry out exclusive access
9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire thread_suspend_count_lock_            |   .. exclusive ..
9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // while Thread::suspend_count_ > 0              |   .. exclusive ..
9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   - wait on Thread::resume_cond_              |   .. exclusive ..
10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //     (releases thread_suspend_count_lock_)     |   .. exclusive ..
10100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               | Release mutator_lock_
10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               | Request thread resumption by:
10300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - acquiring thread_suspend_count_lock_
10400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - decrementing Thread::suspend_count_ on
10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |     all mutator threads
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   .. waiting ..                               |   - notifying on Thread::resume_cond_
10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    - re-acquire thread_suspend_count_lock_    |   - releasing thread_suspend_count_lock_
10800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release thread_suspend_count_lock_            |  .. running ..
10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire share on mutator_lock_                |  .. running ..
11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  - This could block but the thread still      |  .. running ..
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    has a state of kSuspended and so this      |  .. running ..
11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    isn't an issue.                            |  .. running ..
11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Acquire thread_suspend_count_lock_            |  .. running ..
11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  - we poll here as we're transitioning into   |  .. running ..
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    kRunnable and an individual thread suspend |  .. running ..
11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    request (e.g for debugging) won't try      |  .. running ..
11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    to acquire the mutator lock (which would   |  .. running ..
11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    block as we hold the mutator lock). This   |  .. running ..
11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    poll ensures that if the suspender thought |  .. running ..
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    we were suspended by incrementing our      |  .. running ..
12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    Thread::suspend_count_ and then reading    |  .. running ..
12200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    our state we go back to waiting on         |  .. running ..
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //    Thread::resume_cond_.                      |  .. running ..
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // can_go_runnable = Thread::suspend_count_ == 0 |  .. running ..
12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release thread_suspend_count_lock_            |  .. running ..
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // if can_go_runnable                            |  .. running ..
12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   Change state to kRunnable                   |  .. running ..
12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // else                                          |  .. running ..
12900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //   Goto x                                      |  .. running ..
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  //  .. running ..                                |  .. running ..
13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static ReaderWriterMutex* mutator_lock_;
1328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap.
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_);
1358daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads
13700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // attaching and detaching.
13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* thread_list_lock_ ACQUIRED_AFTER(heap_bitmap_lock_);
1398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Guards lists of classes within the class linker.
14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(thread_list_lock_);
1428daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code
14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // doesn't try to hold a higher level Mutex.
14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(classlinker_classes_lock_)
146accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes
14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Have an exclusive aborting thread.
14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_);
149cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Allow mutual exclusion when manipulating Thread::suspend_count_.
15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // TODO: Does the trade-off of a per-thread lock make sense?
15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_);
15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // One unexpected signal at a time lock.
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_);
15600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Have an exclusive logging thread.
15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_);
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const std::string& GetName() const {
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  BaseMutex(const char* name, MutexLevel level);
17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual ~BaseMutex() {}
17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void RegisterAsLockedWithCurrentThread();
17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void RegisterAsUnlockedWithCurrentThread();
17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void CheckSafeToWait();
17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const MutexLevel level_;  // Support for lock hierarchy.
1810a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes  const std::string name_;
18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
19300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
19700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit Mutex(const char* name, MutexLevel level = kDefaultMutexLevel, bool recursive = false);
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
20000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
20200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION();
20500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void Lock() EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(); }
20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool ExclusiveTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(); }
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveUnlock() UNLOCK_FUNCTION();
21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void Unlock() UNLOCK_FUNCTION() {  ExclusiveUnlock(); }
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsExclusiveHeld() const;
2178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertExclusiveHeld() {
22025fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsExclusiveHeld());
22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertHeld() { AssertExclusiveHeld(); }
22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeldExclusive() {
22825fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsExclusiveHeld());
23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeld() { AssertNotHeldExclusive(); }
23300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
23800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
24000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
24100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
24400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
24500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
246f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
2473efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes  friend class MutexTester;
2488daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
2498daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2508daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
25100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
25600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
25800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
25900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
26000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
26200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
26300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
26400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
26500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
2688daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderWriterMutex(const char* name, MutexLevel level = kDefaultMutexLevel);
27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION();
27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void WriterLock() EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(); }
27700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
27900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ExclusiveUnlock() UNLOCK_FUNCTION();
28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void WriterUnlock() UNLOCK_FUNCTION() {  ExclusiveUnlock(); }
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
28300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
28466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool ExclusiveLockWithTimeout(const timespec& abs_timeout) EXCLUSIVE_TRYLOCK_FUNCTION(true);
28666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
28700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void SharedLock() SHARED_LOCK_FUNCTION();
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ReaderLock() SHARED_LOCK_FUNCTION() { SharedLock(); }
29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool SharedTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void SharedUnlock() UNLOCK_FUNCTION();
29700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void ReaderUnlock() UNLOCK_FUNCTION() { SharedUnlock(); }
29800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
30000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsExclusiveHeld() const;
30100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
30300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertExclusiveHeld() {
30425fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
30500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsExclusiveHeld());
30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
3078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertWriterHeld() { AssertExclusiveHeld(); }
3098daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotExclusiveHeld() {
31225fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsExclusiveHeld());
31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
31600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotWriterHeld() { AssertNotExclusiveHeld(); }
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool IsSharedHeld() const;
32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
32100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertSharedHeld() {
32325fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
32400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(IsSharedHeld());
32500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
3268daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
32700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertReaderHeld() { AssertSharedHeld(); }
3288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  void AssertNotHeld() {
33225fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      CHECK(!IsSharedHeld());
33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
33600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
3398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
34000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class MutexTester;
34300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
3448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
3458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
34700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
3485f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
3495f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
350a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ConditionVariable(const std::string& name);
3515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
3525f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3535f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Broadcast();
3545f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Signal();
3555f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Wait(Mutex& mutex);
3565f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void TimedWait(Mutex& mutex, const timespec& ts);
3575f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3585f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
3595f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  pthread_cond_t cond_;
3605f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  std::string name_;
3615f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
3625f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
3635f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
36400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
36500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveLock();
37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveUnlock();
37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
37700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
37900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
38000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
38200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
38600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedLock();
38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedUnlock();
39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
39400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
39500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
39600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
39800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
39900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
40000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
40100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
40200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
40400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
40500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
40600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
40700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
40800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveLock();
40900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
41000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
41200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.ExclusiveUnlock();
41300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
41400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
41500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
41700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
41800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
41900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
42000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
42200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped unlocker/locker for a ReaderWriterMutex that releases read access to mu upon
42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and acquires it again upon destruction.
42500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ReaderMutexUnlock {
42600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
42700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  explicit ReaderMutexUnlock(ReaderWriterMutex& mu) UNLOCK_FUNCTION(mu) : mu_(mu) {
42800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedUnlock();
42900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
43000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
43100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexUnlock() SHARED_LOCK_FUNCTION(mu_) {
43200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    mu_.SharedLock();
43300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
43400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
43500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
43600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
43700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexUnlock);
43800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
43900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexUnlock (lock);" instead of
44000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexUnlock mu(lock)".
44100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexUnlock(x) \
44200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    COMPILE_ASSERT(0, reader_mutex_unlock_declaration_missing_variable_name)
44300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
4448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
4458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif  // ART_SRC_MUTEX_H_
447